SQL查询行到列

时间:2015-10-20 06:17:54

标签: sql sql-server pivot

编辑:我使用Microsoft SQL Server Management Studio来运行查询。 我想是Microsoft SQL Server标准版(64位)。

我有一个复杂的查询要运行。我不知道该怎么做,所以我去写了一个大约500行和很多连接的查询。事情不应该是圆顶的。

我的数据结构是:

id        user_id       question_id     answer1     
1         1             1               a           
2         1             2               c           
3         1             3               a           
4         2             1               c           
5         2             2               a           
...       ...           ...             ...         

有超过700个用户。每个用户已经回答了大约60个问题(第2次,每个问题有2个答案,但如果我能得到第一个答案的好查询,这是无关紧要的)。有一些我不感兴趣的问题(实际上应该跳过)。

我目前的结果如下(效果不错,但查询太快了):

user_id    q1    q2    q3    q4    q8    q9    ...   q60
1          a     b     c     d     b     a     ...   a
2          b     a     c     a     c     b     ...   w
3          y     a     w     ...   ...

所以,基本上我想创建一个数组,比如[1,2,3,4,8,9],说我对那些问题id和查询感兴趣,所以我得到那些列作为上面的例子。我不知道该怎么做。

我目前的查询是:

SELECT C.user_id, Q1, Q2, Q3, Q4, Q8, ...
FROM (
  SELECT A.user_id, Q1, // and here tons of unions

2 个答案:

答案 0 :(得分:1)

编辑:仅使用answer1简化:

DECLARE @tbl TABLE(id INT,user_id INT,question_id INT,answer1 VARCHAR(1),answer2 VARCHAR(1));
INSERT INTO @tbl VALUES     
 (1,1,1,'a','x')           
,(2,1,2,'c','y')           
,(3,1,3,'a','y')           
,(4,2,1,'c','y')         
,(5,2,2,'a','x');

WITH AllAnswers AS
(
    SELECT p.*
    FROM
    (
        SELECT tbl.user_id
              ,'q' + CAST(tbl.question_id AS VARCHAR(10)) AS columnName
              ,answer1
        FROM @tbl AS tbl
    ) AS x
    PIVOT
    (
        MIN(answer1) FOR columnName IN(q1,q2,q3 /*Add your question numbers here*/)
    ) AS p
)
SELECT aa.user_id 
      ,aa.q1
      ,aa.q2
      ,aa.q3 
      /*Get only the questions you want*/
FROM AllAnswers AS aa

/* Result

user_id q1  q2  q3
1       a   c   a
2       c   a   NULL

*/

这可能是您的解决方案:

只是一个简短的解释:当你为每个问题写下两个答案时,我将第二个答案放入测试集。为了允许具有多个列的PIVOT,我使用该技巧将两个答案连接为伪XML。这是由其内部索引再次转移和拆分。

结果是所有用户的列表,其中包含所有问题的答案。使用最后一个SELECT,您可以选择要获取的问题/答案。

DECLARE @tbl TABLE(id INT,user_id INT,question_id INT,answer1 VARCHAR(1),answer2 VARCHAR(1));
INSERT INTO @tbl VALUES     
 (1,1,1,'a','x')           
,(2,1,2,'c','y')           
,(3,1,3,'a','y')           
,(4,2,1,'c','y')         
,(5,2,2,'a','x');

WITH AllAnswers AS
(
    SELECT p.user_id
          ,CAST(p.q1 AS XML).value('x[1]','varchar(1)') AS q1_1
          ,CAST(p.q1 AS XML).value('x[2]','varchar(1)') AS q1_2
          ,CAST(p.q2 AS XML).value('x[1]','varchar(1)') AS q2_1
          ,CAST(p.q2 AS XML).value('x[2]','varchar(1)') AS q2_2
          ,CAST(p.q3 AS XML).value('x[1]','varchar(1)') AS q3_1
          ,CAST(p.q3 AS XML).value('x[2]','varchar(1)') AS q3_2
          /*Add all your question numbers here*/
    FROM
    (
        SELECT tbl.user_id
              ,'q' + CAST(tbl.question_id AS VARCHAR(10)) AS columnName
              ,'<x>' + ISNULL(answer1,'') + '</x><x>' + ISNULL(answer2,'') + '</x>' AS BothAnswers
        FROM @tbl AS tbl
    ) AS x
    PIVOT
    (
        MIN(BothAnswers) FOR columnName IN(q1,q2,q3 /*Add your question numbers here*/)
    ) AS p
)
SELECT aa.user_id 
      ,aa.q1_1 
      ,aa.q1_2 
      ,aa.q2_1 
      ,aa.q2_2 
      ,aa.q3_1 
      ,aa.q3_2 
      /*Get only the questions you want*/
FROM AllAnswers AS aa

答案 1 :(得分:0)

SELECT *
FROM
(
  SELECT [user_id], 
         [answer1],
         row_number() OVER(PARTITION BY [user_id] ORDER BY [question_id]) rn
  FROM [table]
) d
PIVOT
(
  MAX([answer1])
  FOR rn in ([1], [2], [3], [4], [5], [6])
) piv

非常好,一个错误。 user_id = 1没有question_id = 3的答案,但question_id = 4已有答案。我的结果将4的答案放入3

user_id   1    2    3    4    5    6
1         a    b    c         NULL NULL
2         a    b    c    d    NULL NULL

有了这些数据:

user_id    question_id    answer1
1          1              a
1          2              b
1          4              c
1          5                                      (anwer1 = empty string)
1          6              NULL
2          1              a
2          2              b
2          4              c
2          5              d
2          6              NULL

应该给出:

user_id   1    2    3    4    5    6
1         a    b    NULL c         NULL
2         a    b    NULL c    d    NULL

所以错误:如果没有找到记录,那么下一个问题的回答是&#39;使用。