Sql Pivot用于未知列名

时间:2015-06-29 06:27:35

标签: sql tsql sql-server-2012

表格如下:

答案

id    userid setid  questionid  chosenoption    comments
100     1      1      1            7    
101     1      1      2            5    
102     1      1      3                          test1
103     2      1      1            6    
104     2      1      2            4    
105     2      1      3                         comments

上表存储了用户为集合中的问题选择的答案。 每组将有3个问题。只有集合中的最后一个(第三个)问题才会有评论。其余的将有选项值。上表是只有一组的样本。

我正在尝试使用SQL获取如下结果集:

userid   Q1  Q2  Q3  
  1      7   5   test1
  2      6   4   comments

没有。一组中的问题总是3。 只有最后一个问题才会有评论。 QuestionIds未知。 (例如:第2组可能将问题ID设为5,6,7)

我尝试了什么(但给了别的东西):

DECLARE @query VARCHAR(MAX)
DECLARE @questions VARCHAR(MAX)
SELECT @questions = STUFF((SELECT ',' + QuoteName(QuestionId) 
                            FROM Answers WHERE SetId = 1
                            GROUP BY SetId,QuestionId
                            ORDER BY FKQuestionId  
                            FOR XML PATH('')),1,1,'')  
SET @query = 'SELECT * FROM
(
  SELECT UserId,QuestionId,ChosenOption,Comments, ROW_NUMBER() over(partition by UserId
                        ) seq
  FROM Answers
  WHERE SetId=1  
) AS P
PIVOT
(
  min(P.ChosenOption)
  for P.QuestionId IN ('+@questions+')
) AS pvt'
EXECUTE (@query)

我如何实现我想要的目标。我也希望Q1,Q2,Q3成为问题标题。

http://sqlfiddle.com/#!9/449a5a/1

1 个答案:

答案 0 :(得分:1)

试试这个:

DECLARE @t TABLE
    (
      id INT ,
      userid INT ,
      setid INT ,
      questionid INT ,
      chosenoption INT ,
      comments VARCHAR(MAX)
    )

INSERT  INTO @t
VALUES  ( 100, 1, 1, 1, 7, NULL ),
        ( 101, 1, 1, 2, 5, NULL ),
        ( 102, 1, 1, 3, NULL, 'test1' ),
        ( 103, 2, 1, 1, 6, NULL ),
        ( 104, 2, 1, 2, 4, NULL ),
        ( 105, 2, 1, 3, NULL, 'comments' )


select userid,
       max(case when questionid = 1 then chosenoption end) Q1, 
       max(case when questionid = 2 then chosenoption end) Q2,
       max(case when questionid = 3 then comments end) Q3
from @t
group by userid  

输出:

userid  Q1  Q2  Q3
1       7   5   test1
2       6   4   comments

修改

;WITH cte AS(SELECT *, ROW_NUMBER() OVER(PARTITION BY userid ORDER BY id) qid FROM @t)
select userid,
       max(case when qid = 1 then chosenoption end) Q1, 
       max(case when qid = 2 then chosenoption end) Q2,
       max(case when qid = 3 then comments end) Q3
from cte
group by userid