每个唯一ID返回1行而不是多行

时间:2014-05-28 22:38:59

标签: sql sql-server

我有一个sql查询,它返回在会议中注册的学生列表,以及他们对每个会话的首选项。从数据库中提取数据时,每个用户会话选择都显示在其自己的行中,如下所示:

**userid      question              answer**
1        S1 choose: a1, b1, c1      a1
1        S2 choose: a2, b2, c2      b2
1        S3 choose: a3, b3, c3      b3
2        S1 choose: a1, b1, c1      b1
2        S2 choose: a2, b2, c2      c2
2        S3 choose: a3, b3, c3      a3
3        S1 choose: a1, b1, c1      a1
3        S2 choose: a2, b2, c2      b2
3        S3 choose: a3, b3, c3      b3

我想让每个会话成为一个列,以便每个带有问题和答案的用户ID显示在一行中。像这样:

user1 question1 answer1 question2 answer2 question3 answer3
user2 question1 answer1 question2 answer2 question3 answer3
user3 question1 answer1 question2 answer2 question3 answer3

我仅限于我的SQL查询知识,所以我非常感谢您的帮助....我如何才能达到上述结果? 提前致谢

3 个答案:

答案 0 :(得分:0)

在回答您的评论时,如果您知道潜在问题的数量,则可以选择max使用case

select userid,
       max(case when questionid = 1 then question end) question1,
       max(case when questionid = 1 then answer end) answer1,
       max(case when questionid = 2 then question end) question2,
       max(case when questionid = 2 then answer end) answer2,
       ...
from yourtable
group by userid

这假设您有questionid可用。如果没有,您可以使用question字段或创建ROW_NUMBER,它的工作方式相同:

select userid,
       max(case when rn = 1 then question end) question1,
       max(case when rn = 1 then answer end) answer1,
       max(case when rn = 2 then question end) question2,
       max(case when rn = 2 then answer end) answer2,
       ...
from (
    select *, row_number() over (partition by userid order by question) rn
    from yourtable
) t
group by userid

编辑,如果您需要动态解决方案,因为您尝试pivot多个列,首先需要取消结果。执行此操作的一个选项是使用CROSS APPLY。然后你可以PIVOT结果:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME('Question:' + question) +',' + QUOTENAME('Answer:' + question) 
                    from  yourtable
                    group by question
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'select userid, ' + @cols + '
from
(
  select userid,
    col+question new_col,
    value
  from yourtable
  cross apply
  (
    VALUES
        (question, ''Question:''),
        (answer, ''Answer:'')
   ) x (value, col)
) src
pivot
(
  max(value)
  for new_col in (' + @cols + ')
) piv '

execute(@query)

答案 1 :(得分:0)

使用动态SQL。在您使用标识列创建的临时表中选择一个不同的会话列表。

DECLARE @SQL varchar(1000), @Count int, @Counter int
CREATE TABLE #report (userid int)
CREATE TABLE #questions (MyIdx int IDENTITY(1,1), question varchar(50))

INSERT INTO #report (UserID) SELECT DISTINCT userid from mytable
INSERT INTO #questions (question) SELECT DISTINCT question FROM mytable ORDER BY question

SELECT @Count = COUNT(*) FROM #questions, @Counter = 0

WHILE @Counter < @Count
BEGIN
    SET @Counter = @Counter + 1

    SET @SQL = 'ALTER TABLE #report ADD Q' + CONVERT(varchar, @Counter) + ' varchar(50)'

    EXEC (@SQL)

    SET @SQL = 'ALTER TABLE #report ADD A' + CONVERT(varchar, @Counter) + ' varchar(50)'

    EXEC (@SQL)

    SET @SQL = 'UPDATE #report SET Q' + CONVERT(varchar, @Counter) + ' = b.question FROM #report a INNER JOIN mytable b ON a.userid = b.userid INNER JOIN #questions c ON b.question = c.question WHERE c.MyIdx = ' + CONVERT(varchar, @Counter)

    EXEC (@SQL)

    SET @SQL = 'UPDATE #report SET A' + CONVERT(varchar, @Counter) + ' = b.answer FROM #report a INNER JOIN mytable b ON a.userid = b.userid AND a.question = b.Q' + CONVERT(varchar, @Counter)

    EXEC (@SQL)
END

SELECT * FROM #report ORDER BY userid

DROP TABLE #report

DROP TABLE #questions

也就是说,如果你有不明数量的会话。否则,请另外回答。

答案 2 :(得分:0)

如果问题中的示例与您的数据类似,则可能是拆分和联合

SELECT userid
     , q1 = max(q1), a1 = max(a1)
     , q2 = max(q2), a2 = max(a2)
     , q3 = max(q3), a3 = max(a3)
FROM   (SELECT userid
             , q1 = question, a1 = answer
             , q2 = NULL, a2 = NULL
             , q3 = NULL, a3 = NULL
        FROM   table1
        WHERE  left(question, 2) = 'S1'
        UNION ALL
        SELECT userid
             , q1 = NULL, a1 = NULL
             , q2 = question, a2 = answer
             , q3 = NULL, a3 = NULL
        FROM   table1
        WHERE  left(question, 2) = 'S2'
        UNION ALL
        SELECT userid
             , q1 = NULL, a1 = NULL
             , q2 = NULL, a2 = NULL
             , q3 = question, a3 = answer
        FROM   table1
        WHERE  left(question, 2) = 'S3') d
GROUP BY userid

SQLFiddle demo

每个问题代码用于分割数据,而另一个属性a用于所需列。每个数据拆分都有userid,因此它可以用作锚点,用于对其他值进行分组,以便将映射减少到每userid一行。