动态数据透视表列与Sql Server中的相关表

时间:2014-01-28 15:42:11

标签: sql sql-server tsql pivot

我正在尝试使用Pivot动态创建列,但我没有得到正在寻找的正确结果。我需要在每个问题(行)的列中显示所有可能的答案,并且课程中有多个问题。如何将每个可能的答案生成为列名,并按courseId和每行的questionId进行过滤?可能答案的数量因问题而异。这应该通过光标而不是透视来完成吗?

DECLARE @cols AS NVARCHAR(MAX),
        @query  AS NVARCHAR(MAX),
        @courseID float(24) = 1

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(questionID)
            FROM answers
            INNER JOIN questions ON questions.questionID = answers.questionID
            WHERE questions.courseId = @courseID
            order by 1 
                      FOR XML PATH(''), TYPE
                     ).value('.', 'NVARCHAR(MAX)') 
                        , 1, 1, '');

set @query = 'SELECT * from 
            (
                select Q.courseId, C.courseName, Q.question, Q.questionID, A.answer
                from questions Q 
                inner join courses C ON Q.courseId = C.courseId
                inner join answers A  ON A.questionID = Q.questionID
                where (Q.courseId = ''' + Str(@courseID) + ''')
           ) x
            pivot 
            (
                max(answer)
                for questionId in (' + @cols + ')
            ) AS p'


execute(@query)

运行上述内容时我得到了:

[1],[10],[11],[12],[13],[14],[15],[16],[2],[3],[4],[5],[6],[7],[8],[9]

生成的列是questionIds而不是'Answer 1,Answer 2 ... etc',它们没有按顺序显示。

为简洁起见,这里是数据库表中的相关列:

课程

courseId

问题

questionId   question     courseId

答案

AnswerId    questionId    answer

感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

您没有提供有关表结构的许多详细信息,但如果您希望将答案作为列Answer1Answer2等,那么您需要使用{{1}创建列每个问题的答案数量与以下内容类似:

row_number()

这为每个问题的每个答案创建一个序列,然后该序列号用于创建新列名称。然后你将把你的PIVOT代码改为:

SET @cols = STUFF((SELECT ',' + QUOTENAME('Answer'+cast(seq as varchar(10)))
            FROM
            (
                select row_number() over(partition by q.questionid
                                            order by a.answer) seq
                from answers a
                INNER JOIN questions q
                    ON q.questionID = a.questionID
                WHERE q.courseId = @courseID
            ) d
            group by seq
            order by seq
                    FOR XML PATH(''), TYPE
                 ).value('.', 'NVARCHAR(MAX)') 
                    , 1, 1, '');