SQL查询行到列

SQL查询行到列,sql,sql-server,pivot,Sql,Sql Server,Pivot,编辑:我使用Microsoft SQL Server Management Studio运行查询。 我想是微软SQL Server标准版64位 我有一个复杂的查询要运行。我不知道怎么做,所以我去写了一个查询,大约有500行和许多连接。事情不应该是这样的 我的数据结构是: id user_id question_id answer1 1 1 1 a 2

编辑:我使用Microsoft SQL Server Management Studio运行查询。 我想是微软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

编辑:仅使用回答进行简化1:

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

*/
这是否是您的解决方案:

只是一个简短的解释:当你为每个问题写下两个答案时,我将第二个答案放入测试集中。为了允许一个包含多个列的轴,我使用了将两个答案作为伪XML连接的技巧。这是支点,并由其内部索引再次分开

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

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
对于一个bug来说,它工作得非常好。用户\u id=1对问题\u id=3没有答案,但对问题\u id=4有答案。我的结果将答案放在4到3之间:

根据这些数据:

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

因此错误:如果没有找到记录,则使用“下一个问题”的答案。

在这种情况下,您必须编写动态Sql,即使用数组列表生成查询,然后执行它。在sql server中,您可以通过EXECSelect运行动态查询…您的示例数据和输出不匹配,这是故意的吗?另外,请标记您的数据库管理系统。您正在使用哪些数据库管理系统?博士后?甲骨文?,甲骨文。是的,输出不匹配,没有真正注意到这一点。内容无关紧要,是关于表结构的。我使用的Microsoft SQL Server Management Studio不适合我使用的Oracle SMS不能与Oracle一起使用。我将着手解决这个问题,感谢您提供的详细示例!对于这两个答案,我的意思是表中有两个答案列。参见“answer1”,还有一个“answer2”。我不需要看第二个答案:我想要两个结果表,一个用于答案1,一个用于答案2。因此,我可以使用该查询并将其设置为从列answer1中获取答案,然后从相同的查询中获取答案,但来自anwer2列。@Tjab,我简化了我的示例,仅使用answer1。我不认为,这可以做得容易得多。。。在最终选择中,您可以自由选择只选择您想要的列。您的编号将返回一个运行编号。如果表中没有答案,rn将跳过一个值。你可以尝试使用理货台,但我的答案中的方法肯定更可靠。。。怎么了?嗨,你能解决你的问题吗?我编辑的答案对你有帮助吗?如果是的话,请投票支持它,如果它解决了您的问题,请将它标记为已接受,谢谢!是的,谢谢!对不起,我回来得太晚了。标记为已接受,再次感谢!
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