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'

如果始终只有相同的三个问题,我知道如何实现这一点,但是该数据库托管多个调查,这些调查可能具有任意数量的唯一 QuestionID,因此我需要 Q1、Q2、Q3 列是动态的,具体取决于其数量和 ID调查的问题。

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

希望这是有道理的。谢谢。

4

2 回答 2

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);
于 2013-07-18T14:13:10.723 回答
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')
于 2013-07-17T15:24:27.520 回答