假设我有下表代表用户调查系统的结果。
SurveyID ResponseID QuestionID Answer
-------- ---------- ---------- ------
1 1 1 'Answer 1'
1 1 2 'Answer 2'
1 1 3 'Answer 3'
1 2 1 'red'
1 2 2 'blue'
1 2 3 'green'
我想要的是一个旋转输出,如下所示。
SurveyID ResponseID Q1 Q2 Q3
-------- ---------- -- -- --
1 1 'Answer 1' 'Answer 2' 'Answer 3'
1 2 'red' 'blue' 'green'
如果总是只有相同的三个问题,我知道如何实现这个目标,但是这个数据库包含多个调查,这些调查可能有任意数量的唯一QuestionID,所以我需要Q1,Q2,Q3列是动态的,具体取决于数量和该调查问题的ID。
我认为这是一个相当标准的问题,但我找不到任何完全满足这个问题的东西。任何解决方案都必须与SQL Server 2005一起使用。
希望这是有道理的。感谢。
答案 0 :(得分:0)
1)枢纽需要聚合。您可能事先知道您只对一行感兴趣,但SQL不知道这一点。如果您每组只处理一行,只需使用MIN()
作为汇总。
2)动态数据透视不是SQL的标准问题。这是表示层的任务,而不是数据层。您将不得不使用动态SQL,它仍然无法处理任意数量的列,如果您不小心,将会打开注入攻击。
如果你仍然想这样做:
CREATE TABLE #t (Surveyid int, Responseid int, Questionid int, Answer varchar(max))
INSERT #t VALUES (1,1,1,'Answer1'),(1,1,2,'Answer2'),(1,1,3,'Answer3'),(1,2,1,'red'),(1,2,2,'blue'),(1,2,3,'green')
DECLARE @qids nvarchar(4000)
SELECT @qids = COALESCE(@qids+',','') + qid
FROM (SELECT DISTINCT QUOTENAME(Questionid) qid FROM #t) t
EXEC ('SELECT [SurveyID],[ResponseID],'+@qids+' FROM #t PIVOT(MIN(Answer) FOR Questionid IN('+@qids+')) p')
答案 1 :(得分:0)
好的,终于发现了如何做到这一点,以为我会分享。
DECLARE @SurveyID SMALLINT;
DECLARE @SQL as VARCHAR(MAX);
DECLARE @Columns AS VARCHAR(MAX);
DECLARE @ColumnHeadings AS Varchar(MAX);
SET @SurveyID = 1;
SELECT
@Columns = COALESCE(@Columns + ', ','') + '[' + QuestionID + ']'
,@ColumnHeadings = COALESCE(@ColumnHeadings + ', ','') + '[' + QuestionID + '] AS [Q' + QuestionNumber + ']'
FROM
(
SELECT DISTINCT
CAST(a.QuestionID AS VARCHAR) AS QuestionID
,CASE WHEN q.QuestionNumber IS NULL THEN '' ELSE q.QuestionNumber END AS QuestionNumber
FROM dbo.Answers AS a
JOIN dbo.Questions AS q
ON a.QuestionID = q.ID
JOIN dbo.SurveyResponses AS r
ON a.ResponseID = r.ID
WHERE r.SurveyID = @SurveyID
)
SET @SQL = '
WITH PivotData AS
(
SELECT
a.QuestionID
,a.ResponseID
,a.Answer
FROM dbo.Answers AS a
JOIN dbo.SurveyResponses AS r
ON a.ResponseID = r.ID
)
SELECT
ResponseID
,' + @ColumnHeadings + '
FROM PivotData
PIVOT
(
MAX(Answer)
FOR QuestionID
IN (' + @Columns + ')
) AS PivotResult
ORDER BY ResponseID' ASC
EXEC (@SQL);