从一列中加入多个值,从另一列中选择 table
Join multiple values from one column, selected from another table
考虑到这些简化的多项选择表,其中有时不止一个答案是正确的:
STUDENT_ANSWERS
AnswerID | StudentID | QuestionID | Answers
-------------------------------------------
1 | 1 | 1 | C,D
QUESTION_ANSWERS
QuestionID | Answer | Text
-------------------------------------------------
1 | A | This is answer A
1 | B | B could also be correct
1 | C | Maybe it's C?
1 | D | Definitely D!
我如何做一个 select 将答案翻译成他们的描述?
我的起点:
SELECT *
FROM STUDENT_ANSWERS sa
LEFT OUTER JOIN QUESTION_ANSWERS qa ON qa.Answer IN sa.Answers???
-- Doesn't seem to work as IN requires a format of ('C','D') while I have 'C,D'
期望的输出:
AnswerID | StudentID | QuestionID | AnswerDescriptions
-------------------------------------------
1 | 1 | 1 | Maybe it's C?,Definitely D!
因此,描述只需替换代码,而不是为每个答案获取一行。
你的问题是 table STUDENT_ANSWERS
的结构。每个答案应该一行:
AnswerID | StudentID | QuestionID | Answer
-------------------------------------------
1 | 1 | 1 | C
2 | 1 | 1 | D
现在,假设你不能做任何改变(阅读:修复)这个,你可以通过附加逗号和使用 LIKE 来捏造它:
select *
from STUDENT_ANSWERS a
join QUESTION_ANSWERS q on ',' + a.Answers + ',' like '%,' + q.Answer + ',%'
and a.QuestionID = q.QuestionID
请注意,假设您永远不会在 QUESTION_ANSWERS.Answer
中看到文本 ,
。它也永远无法使用索引,所以它会比慢更慢。
如果你绝对必须在数据库中将其格式化为一行,你可以使用STUFF
和FOR XML PATH('')
技巧来连接结果行。
这是仅使用 T-SQL
语句的完整工作示例。我会建议您创建单独的函数来拆分 CSV
那个 returns 行集。此外,如果您正在处理大量数据,您可能需要创建一个 CLR
函数来拆分值。看看this article(这里有你需要的一切)。
DECLARE @StudentAnswers TABLE
(
[AnswerID] INT
,[StudentID] INT
,[QuestionID] INT
,[Answers] VARCHAR(256)
);
DECLARE @QuestionAnswers TABLE
(
[QuestionID] INT
,[Answer] CHAR
,[Text] VARCHAR(256)
);
INSERT INTO @StudentAnswers ([AnswerID], [StudentID], [QuestionID], [Answers])
VALUES (1, 1, 1, 'C,D')
,(2, 2, 1, 'A');
INSERT INTO @QuestionAnswers ([QuestionID], [Answer], [Text])
VALUES (1, 'A', 'This is answer A')
,(1, 'B', 'B could also be correct')
,(1, 'C', 'Maybe it''s C?')
,(1, 'D', 'Definitely D!');
SELECT SA.[AnswerID]
,SA.[StudentID]
,SA.[QuestionID]
,T.c.value('.', 'CHAR')
,QA.[Text]
FROM @StudentAnswers SA
CROSS APPLY
(
SELECT CAST('<i>' + REPLACE([Answers], ',', '</i><i>') + '</i>' AS XML) Answers
) DS
CROSS APPLY DS.Answers.nodes('i') T(c)
INNER JOIN @QuestionAnswers QA
ON SA.[QuestionID] = QA.[QuestionID]
AND T.c.value('.', 'CHAR') = QA.[Answer];
试试这个
select answerid,studentid,a.QuestionID,group_concat(b.text) from student_answers a left join QUESTION_ANSWERS b on b.questionid= a.questionid and FIND_IN_SET(b.Answer, a.Answers)
group by a.questionid
绝对有效。
考虑到这些简化的多项选择表,其中有时不止一个答案是正确的:
STUDENT_ANSWERS
AnswerID | StudentID | QuestionID | Answers
-------------------------------------------
1 | 1 | 1 | C,D
QUESTION_ANSWERS
QuestionID | Answer | Text
-------------------------------------------------
1 | A | This is answer A
1 | B | B could also be correct
1 | C | Maybe it's C?
1 | D | Definitely D!
我如何做一个 select 将答案翻译成他们的描述?
我的起点:
SELECT *
FROM STUDENT_ANSWERS sa
LEFT OUTER JOIN QUESTION_ANSWERS qa ON qa.Answer IN sa.Answers???
-- Doesn't seem to work as IN requires a format of ('C','D') while I have 'C,D'
期望的输出:
AnswerID | StudentID | QuestionID | AnswerDescriptions
-------------------------------------------
1 | 1 | 1 | Maybe it's C?,Definitely D!
因此,描述只需替换代码,而不是为每个答案获取一行。
你的问题是 table STUDENT_ANSWERS
的结构。每个答案应该一行:
AnswerID | StudentID | QuestionID | Answer ------------------------------------------- 1 | 1 | 1 | C 2 | 1 | 1 | D
现在,假设你不能做任何改变(阅读:修复)这个,你可以通过附加逗号和使用 LIKE 来捏造它:
select *
from STUDENT_ANSWERS a
join QUESTION_ANSWERS q on ',' + a.Answers + ',' like '%,' + q.Answer + ',%'
and a.QuestionID = q.QuestionID
请注意,假设您永远不会在 QUESTION_ANSWERS.Answer
中看到文本 ,
。它也永远无法使用索引,所以它会比慢更慢。
如果你绝对必须在数据库中将其格式化为一行,你可以使用STUFF
和FOR XML PATH('')
技巧来连接结果行。
这是仅使用 T-SQL
语句的完整工作示例。我会建议您创建单独的函数来拆分 CSV
那个 returns 行集。此外,如果您正在处理大量数据,您可能需要创建一个 CLR
函数来拆分值。看看this article(这里有你需要的一切)。
DECLARE @StudentAnswers TABLE
(
[AnswerID] INT
,[StudentID] INT
,[QuestionID] INT
,[Answers] VARCHAR(256)
);
DECLARE @QuestionAnswers TABLE
(
[QuestionID] INT
,[Answer] CHAR
,[Text] VARCHAR(256)
);
INSERT INTO @StudentAnswers ([AnswerID], [StudentID], [QuestionID], [Answers])
VALUES (1, 1, 1, 'C,D')
,(2, 2, 1, 'A');
INSERT INTO @QuestionAnswers ([QuestionID], [Answer], [Text])
VALUES (1, 'A', 'This is answer A')
,(1, 'B', 'B could also be correct')
,(1, 'C', 'Maybe it''s C?')
,(1, 'D', 'Definitely D!');
SELECT SA.[AnswerID]
,SA.[StudentID]
,SA.[QuestionID]
,T.c.value('.', 'CHAR')
,QA.[Text]
FROM @StudentAnswers SA
CROSS APPLY
(
SELECT CAST('<i>' + REPLACE([Answers], ',', '</i><i>') + '</i>' AS XML) Answers
) DS
CROSS APPLY DS.Answers.nodes('i') T(c)
INNER JOIN @QuestionAnswers QA
ON SA.[QuestionID] = QA.[QuestionID]
AND T.c.value('.', 'CHAR') = QA.[Answer];
试试这个
select answerid,studentid,a.QuestionID,group_concat(b.text) from student_answers a left join QUESTION_ANSWERS b on b.questionid= a.questionid and FIND_IN_SET(b.Answer, a.Answers)
group by a.questionid
绝对有效。