我认为通过示例展示是最快的,所以这里是我的问题的简化版本。我正在使用SQL Server。
这是数据模型
SURVEY QUESTION ANSWER
------ -------- -------
surveyId questionId answerId
questionText surveyId
questionId
answerText
以下是一些示例数据
SURVEY QUESTION
---------- ------------ --------------
| surveyId | | questionId | questionText |
---------- ------------ --------------
| 1 | | 1 | Name |
| 2 | | 2 | E-Mail |
---------- | 3 | Address |
| 4 | Phone |
------------ --------------
ANSWER
-----------------------------------------------
| answerId | surveyId | questionId | answerText |
-----------------------------------------------
| 1 | 1 | 1 | John |
| 2 | 1 | 2 | john@aa.bb |
| 3 | 1 | 3 | New York |
| 4 | 1 | 4 | 1112223344 |
| 5 | 2 | 1 | Pete |
| 6 | 2 | 2 | pete@cc.dd |
| 7 | 2 | 3 | Boston |
| 8 | 2 | 4 | 5556667788 |
-----------------------------------------------
最后,这是我想要选择的内容
RESULT
------------------------------
| surveyId | name | email |
------------------------------
| 1 | John | john@aa.bb |
| 2 | Pete | pete@dd.cc |
------------------------------
我希望能够在运行时指定我在最终表中需要哪些列。现在我可以通过以下方式获得此结果
SELECT rName.surveyId, rName.requestor, rEmail.email
FROM (SELECT a.answerText AS name, a.surveyId
FROM answer a INNER JOIN question q ON a.questionId = q.questionId
WHERE a.surveyId = @surveyId AND q.questionText = 'Name') AS rName
INNER JOIN
(SELECT a.answerText AS name, a.surveyId
FROM answer a INNER JOIN question q ON a.questionId = q.questionId
WHERE a.surveyId = @surveyId AND q.questionText = 'E-Mail') AS rEmail
ON rName.questionnaireId = rEmail.questionnaireId
正如您所看到的,它很难看,并且包含重复的代码。有没有办法做到这个清洁?
答案 0 :(得分:2)
SELECT a.surveyID,
MAX(CASE WHEN c.questionText = 'Name' THEN b.answerText ELSE NULL END) name,
MAX(CASE WHEN c.questionText = 'E-Mail' THEN b.answerText ELSE NULL END) email
FROM Survey a
INNER JOIN Answer b
ON a.surveyID = b.surveyID
INNER JOIN Question c
ON b.questionID = c.questionID
GROUP BY a.surveyID
答案 1 :(得分:2)
SQL Server有一个PIVOT
函数可用于此类查询。如果您知道要转换的值,则可以对值进行硬编码:
select surveyid, name, [e-mail]
from
(
select a.answertext,
q.questiontext,
s.surveyid
from survey s
left join answer a
on s.surveyid = a.surveyid
left join question q
on a.questionid = q.questionid
) src
pivot
(
max(answertext)
for questiontext in ([name], [e-mail])
) p
现在,如果你有一个未知数量的值,你可以使用动态sql来pivot
数据:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(questiontext)
from question
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT surveyid, ' + @cols + ' from
(
select a.answertext,
q.questiontext,
s.surveyid
from survey s
left join answer a
on s.surveyid = a.surveyid
left join question q
on a.questionid = q.questionid
) x
pivot
(
max(answertext)
for questiontext in (' + @cols + ')
) p '
execute(@query)
答案 2 :(得分:2)
select *
from
(
select
s.surveyid,
q.questionText,
a.answerText
from SURVEY as s
cross join QUESTION as q
left outer join ANSWER as a on a.questionId = q.questionId and a.surveyId = s.SurveyId
) as M
pivot
(
min(M.answerText)
for M.questionText in ([Name], [E-Mail], [Address], [Phone])
) as P
答案 3 :(得分:1)
可能不是PIVOT的“正确”用法,但以下方法可以解决(请求SQL2005或更高版本):
SELECT surveryId, [1] AS [name], [2] AS [e-mail]
FROM
( SELECT a.surveryId, q.QuestionId, a.answerText
FROM dbo.Question q
INNER JOIN dbo.Answer a ON a.questionId = q.QuestionId
) tmp
PIVOT (
MAX(answerText)
FOR questionId IN ([1], [2])
) PvtTable