在构建列标题时加入动态SQL

时间:2014-09-12 15:14:22

标签: sql sql-server sql-server-2012

我有以下两个表:

测验表:

QuizNo |   Status
  1       Reviewed
  2       Not Reviewed

测验响应表:

QuizNo  | QuestionID | Response
1             11         Yes
2             13         No
2             11         Yes
1             13         No

这是预期的结果(11和13是问题ID):

QuizNo  |  Status     |   11   |    13
  1        Reviewed       Yes       No
  2        Not Reviewed   Yes       No

这是我当前的查询,它无效:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(QuestionID) 
                    from Quiz
                    INNER JOIN QuizResponse x ON QuizNo = x.QuizNo
                    group by QuestionID, QuizNo
                    order by QuestionID
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') ,1,1,'')

set @query = N'SELECT ' + @cols + N' from 
             (
                select QuestionID
                from QuizResponse
            ) x
            pivot 
            (
                max(QuestionID)
                for QuestionID in (' + @cols + N')
            ) p '

exec sp_executesql @query;

您如何完成/更改查询以获得预期结果?

TIA!

2 个答案:

答案 0 :(得分:1)

你很接近,但在查询完成之前还需要做一些事情。

The Stuff功能中的查询需要使用表别名指定两个QuizNo。它也不应该按QuizID分组,否则你最终会得到重复的列定义(每个带有QuestionID 11的QuizID一个[11])。所以整理了这个小组。

最后,更新动态SQL以选择不被转动的列,并选择max(Response)而不是QuestionID作为每个单元格的数据。

请参阅SQLFiddle example

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(QuestionID) 
                    from Quiz Q
                    INNER JOIN QuizResponse x ON Q.QuizNo = x.QuizNo
                    GROUP BY QuestionID
                    ORDER BY QuestionID
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') ,1,1,'')

set @query = N'SELECT QuizNo, [Status], ' + @cols + N' from 
             (
                select QR.QuizNo, Q.[Status], QR.QuestionID, QR.Response
                from QuizResponse QR
                  inner join Quiz Q on QR.QuizNo = Q.QuizNo
            ) x
            pivot 
            (
                max(Response)
                for QuestionID in (' + @cols + N')
            ) p '

exec sp_executesql @query;

答案 1 :(得分:0)

我会使用条件聚合来做到这一点:

select q.quizno, q.status,
       max(case when qr.questionid = 11 then qr.response end) as [11],
       max(case when qr.questionid = 13 then qr.response end) as [13]
from quiz q join
     quizreponse qr
     on qr.quizno = q.quizno
group by q.quizno, q.status;