2014-01-28 129 views
0

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

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而不是“答案1,答案2 ...等”,并且它们并不显示在订购。

为了简洁这里的目的是相关的列数据库中的表:

课程

courseId 

问题

questionId question  courseId 

答案

AnswerId questionId answer 

任何帮助表示赞赏。

回答

1

你没有提供你的表结构中的许多细节,但如果你想要的答案为列,即Answer1Answer2等,那么你需要创建一个使用row_number()针对每类似问题答案的数目列以下内容:

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, ''); 

这将为每个问题回答每一个序列,然后该序列号是用来创建新的列名。那么你会改变你的PIVOT代码:

set @query = 'SELECT * 
      from 
      (
       select Q.courseId, C.className, Q.question, Q.questionID, A.answer, 
        ''Answer''+cast(row_number() over(partition by q.questionid 
                 order by a.answer) as varchar(10)) seq 
       from questions Q 
       inner join classes 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 seq in (' + @cols + ') 
      ) AS p' 


execute(@query) 
+0

对不起,缺乏细节。我编辑我的问题,包括一些表结构。无论如何,你的例子完美无缺。谢谢! – Drew