Условно выберите значение в одной из двух таблиц - PullRequest
3 голосов
/ 27 марта 2019

У меня есть анкета-приложение, в котором пользователь будет отправлять ответы. Некоторые вопросы основаны на тексте, а некоторые имеют фиксированные параметры.

Значения сохраняются в таблице tAnswers либо как введенное текстовое значение, либо как Id выбранной опции. Существует столбец QuestionTypeId, который определяет, является ли ответ ссылкой на tOptions.Id.

Я хочу выбрать ответы, возвращая введенное значение или значение, относящееся к выбранному идентификатору.

Например;

SET NOCOUNT ON
DECLARE @tSubmissions TABLE (Id INT)
DECLARE @tSubmissionQuestions TABLE (SubmissionId INT, QuestionId INT)
DECLARE @tQuestions TABLE (Id INT, QuestionText NVARCHAR(MAX), ColName NVARCHAR(MAX), QuestionTypeId INT)
DECLARE @tOptions TABLE (Id INT, OptionValue NVARCHAR(MAX), OptionGroupId INT)
DECLARE @tAnswers TABLE (Id INT IDENTITY(1,1), SubmissionId INT, QuestionId INT, AnswerValue NVARCHAR(MAX))

INSERT INTO @tQuestions VALUES (1, 'What is your name?', 'Name', 1)
INSERT INTO @tQuestions VALUES (2, 'What is your age?', 'Age', 1)
INSERT INTO @tQuestions VALUES (3, 'What is your gender?', 'Gender', 2)
INSERT INTO @tQuestions VALUES (4, 'What is your favourite colour?', 'Colour', 2)

-- Answers for question 3 - gender
INSERT INTO @tOptions VALUES (1, 'Male', 1)
INSERT INTO @tOptions VALUES (2, 'Female', 1)

-- answers for question 4 - colour
INSERT INTO @tOptions VALUES (3, 'Blue', 2)
INSERT INTO @tOptions VALUES (4, 'Green', 2)
INSERT INTO @tOptions VALUES (5, 'Red', 2)
INSERT INTO @tOptions VALUES (6, 'Yellow', 2)

INSERT INTO @tSubmissions VALUES (1)
INSERT INTO @tSubmissions VALUES (2)
INSERT INTO @tSubmissions VALUES (3)

INSERT INTO @tSubmissionQuestions VALUES (1, 1)
INSERT INTO @tSubmissionQuestions VALUES (1, 2)
INSERT INTO @tSubmissionQuestions VALUES (1, 3)
INSERT INTO @tSubmissionQuestions VALUES (1, 4)
INSERT INTO @tSubmissionQuestions VALUES (2, 1)
INSERT INTO @tSubmissionQuestions VALUES (2, 2)
INSERT INTO @tSubmissionQuestions VALUES (2, 3)
INSERT INTO @tSubmissionQuestions VALUES (2, 4)
INSERT INTO @tSubmissionQuestions VALUES (3, 1)
INSERT INTO @tSubmissionQuestions VALUES (3, 2)
INSERT INTO @tSubmissionQuestions VALUES (3, 3)
INSERT INTO @tSubmissionQuestions VALUES (3, 4)

-- form submissions
INSERT INTO @tAnswers (SubmissionId, QuestionId, AnswerValue) VALUES (1, 1, 'Tony Stark')
INSERT INTO @tAnswers (SubmissionId, QuestionId, AnswerValue) VALUES (1, 2, '39')
INSERT INTO @tAnswers (SubmissionId, QuestionId, AnswerValue) VALUES (1, 3, '1') -- reference to @tOptions
INSERT INTO @tAnswers (SubmissionId, QuestionId, AnswerValue) VALUES (1, 4, '5') -- reference to @tOptions

INSERT INTO @tAnswers (SubmissionId, QuestionId, AnswerValue) VALUES (2, 1, 'Pepper Potts')
INSERT INTO @tAnswers (SubmissionId, QuestionId, AnswerValue) VALUES (2, 2, '38')
INSERT INTO @tAnswers (SubmissionId, QuestionId, AnswerValue) VALUES (2, 3, '2') -- reference to @tOptions
INSERT INTO @tAnswers (SubmissionId, QuestionId, AnswerValue) VALUES (2, 4, '6') -- reference to @tOptions

INSERT INTO @tAnswers (SubmissionId, QuestionId, AnswerValue) VALUES (3, 1, 'James Rhodes')
INSERT INTO @tAnswers (SubmissionId, QuestionId, AnswerValue) VALUES (3, 2, '41') -- has choosen to not answer question 3
INSERT INTO @tAnswers (SubmissionId, QuestionId, AnswerValue) VALUES (3, 4, '3') -- reference to @tOptions

SELECT 
    s.Id as SubmissionId, q.Id as QuestionId, a.AnswerValue
FROM 
    @tSubmissions s
INNER JOIN @tSubmissionQuestions sq
    ON sq.SubmissionId = s.Id
INNER JOIN @tQuestions q
    ON q.Id = sq.QuestionId
LEFT JOIN @tAnswers a
    ON a.QuestionId = q.Id
    AND a.SubmissionId = s.Id

DBFiddle

Это возвращает;

SubmissionId | QuestionId | AnswerValue
=============|============|===============
1            | 1          |  Tony Stark
1            | 2          |  39
1            | 3          |  1     <-- this is the Id of the selected option
1            | 4          |  5     <-- this is the Id of the selected option
2            | 1          |  Pepper Potts
2            | 2          |  38
2            | 3          |  2     <-- this is the Id of the selected option
2            | 4          |  6     <-- this is the Id of the selected option
3            | 1          |  James Rhodes
3            | 2          |  41
3            | 3          |  NULL  <-- the option was not selected
3            | 4          |  3     <-- this is the Id of the option

Вместо этого я хотел бы;

SubmissionId | QuestionId | AnswerValue
=============|============|===============
1            | 1          |  Tony Stark
1            | 2          |  39
1            | 3          |  Male    <-- this is the value of the selected option
1            | 4          |  Red     <-- this is the value of the selected option
2            | 1          |  Pepper Potts
2            | 2          |  38
2            | 3          |  Female  <-- this is the value of the selected option
2            | 4          |  Yellow  <-- this is the value of the selected option
3            | 1          |  James Rhodes
3            | 2          |  41
3            | 3          |  NULL    <-- the option was not selected
3            | 4          |  Blue    <-- this is the value of the selected option

Как условно получить значения из таблицы tOptions?

Ответы [ 3 ]

2 голосов
/ 27 марта 2019

Пожалуйста, попробуйте это.

SELECT 
    s.Id as SubmissionId, q.Id as QuestionId,
    CASE WHEN q.QuestionTypeId = 1 THEN 
    a.AnswerValue
    ELSE 
    ISNULL((SELECT  CONVERT(VARCHAR(100),OptionValue) FROM @tOptions o WHERE o.Id = a.AnswerValue),a.AnswerValue)
    END  AS AnswerValue
FROM 
    @tSubmissions s
INNER JOIN @tSubmissionQuestions sq
    ON sq.SubmissionId = s.Id
INNER JOIN @tQuestions q
    ON q.Id = sq.QuestionId
LEFT JOIN @tAnswers a
    ON a.QuestionId = q.Id
    AND a.SubmissionId = s.Id
ORDER BY s.Id ASC
2 голосов
/ 27 марта 2019

Я бы сделал два столбца в таблице Answers. Тот, который у вас есть AnswerValue NVARCHAR(MAX) NULL, а другой AnswerOptionID int NULL. Это сделает объединение более эффективным и устранит проблемы, когда движок попытается преобразовать текст "Tony Stark" в целое число.

Но, учитывая схему как есть, здесь есть один вариант. Я добавил LEFT JOIN в таблицу @tOptions. Обратите внимание, что я конвертирую целочисленные идентификаторы в текст, а не наоборот.

SELECT 
    s.Id as SubmissionId, q.Id as QuestionId
    -- , a.AnswerValue, Options.OptionValue
    ,CASE WHEN q.QuestionTypeId = 2 
        THEN Options.OptionValue 
        ELSE a.AnswerValue 
    END AS AnswerText
FROM 
    @tSubmissions s
    INNER JOIN @tSubmissionQuestions sq ON sq.SubmissionId = s.Id
    INNER JOIN @tQuestions q ON q.Id = sq.QuestionId
    LEFT JOIN @tAnswers a
        ON  a.QuestionId = q.Id
        AND a.SubmissionId = s.Id
    LEFT JOIN @tOptions AS Options
        ON  q.QuestionTypeId = 2
        AND a.AnswerValue = CAST(Options.Id AS NVARCHAR(MAX))
;
2 голосов
/ 27 марта 2019

Я думаю, это то, что вы ищете: Еще LEFT JOIN на tOptions для выбора значений, в случае QuestionTypeId = 2 Я просто добавил ISNUMERIC, чтобы избежать ошибок преобразования.

SELECT 
    s.Id as SubmissionId, 
    q.Id as QuestionId, 
    COALESCE(t.OptionValue,a.AnswerValue) AS AnswerValue
FROM 
    @tSubmissions s
INNER JOIN @tSubmissionQuestions sq
    ON sq.SubmissionId = s.Id
INNER JOIN @tQuestions q
    ON q.Id = sq.QuestionId
LEFT JOIN @tAnswers a
    ON a.QuestionId = q.Id
    AND a.SubmissionId = s.Id
LEFT JOIN @tOptions t
        ON q.QuestionTypeId = 2
       AND ISNUMERIC(a.AnswerValue) = 1
       AND a.AnswerValue = t.Id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...