简体   繁体   中英

Sql Pivot for unknown column names

The table is as follows:

Answers

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

The above table stores the answers selected by users for questions in a set. Each set will have 3 questions. Only the last (3rd) question in a set will have comments. The rest of them will have option values. The above table is a sample with only a single set.

I am trying to get a result set as follows using SQL:

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

The no. of questions in a set will always be 3. Only the last question will have comments. The QuestionIds are unknown. (eg: Set 2 may have the questionIds as 5,6,7)

What I tried (but giving something else):

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)

How can I achieve what I want. I also want Q1,Q2,Q3 as question titles.

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

Try this:

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  

Output:

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

EDIT:

;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  

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM