2013-07-17 36 views
0

比方说,我有下表代表用户调查系统的结果。如何动态将行值转换为不含聚合的列?

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' 

我知道如何做到这一点,如果有永远只有三个同样的问题,但这个数据库主机可能有任意数量的独特QuestionIDs的,所以我需要的Q1,Q2,Q3列是动态的,根据多个调查根据调查问题的数量和标识。

我认为这将是一个相当标准的问题,但我找不到任何完全满足此问题的东西。任何解决方案都必须与SQL Server 2005一起工作。

希望有道理。谢谢。

+0

看看第二个答案此链接http://stackoverflow.com/questions/17700957/dynamic-pivot-for-multiple-columns/17701731?noredirect=1#comment25796267_17701731...does上的东西那你寻找 –

+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],'[email protected]+' FROM #t PIVOT(MIN(Answer) FOR Questionid IN('[email protected]+')) p') 
0

OK,终于发现了怎么做,所以以为我也有同感。

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);