2013-07-17 33 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);