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'

常に同じ 3 つの質問しかない場合にこれを達成する方法を知っていますが、このデータベースは一意の QuestionID をいくつでも持つことができる複数の調査をホストしているため、その数と ID に応じて Q1、Q2、Q3 列を動的にする必要があります。調査の質問。

これはかなり標準的な問題だと思っていましたが、この問題を完全に満たすものは見つかりませんでした。どのソリューションも SQL Server 2005 で動作する必要があります。

それが理にかなっていることを願っています。ありがとう。

4

2 に答える 2

0

1) ピボットには集計が必要です。関心があるのは 1 行のみであることは事前にわかっているかもしれませんが、SQL はそれを知りません。グループごとに 1 つの行のみを処理する場合は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 に答える
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);
于 2013-07-18T14:13:10.723 に答える