【问题标题】:SQL Server : Pivot with custom column namesSQL Server:使用自定义列名进行数据透视
【发布时间】:2013-05-12 23:21:17
【问题描述】:

我需要使用自定义列名来旋转表格。请看下表格式。

当前格式

ID            question                            Answer
4482515   I would like to be informed  by mail.   No
4482515   Plan to Purchase?                       Over 12 months
4482515   Test Question Text                      some Answer

我想以以下格式显示数据。

所需格式

ID       question 1                            Answer1   question 2         Answer 2
4482515  I would like to be informed  by mail. NO        Plan to Purchase?  Over 12 months 

请注意:我不知道一行中的问题和答案的数量,因此该列的 question1 Answer1 应该是动态生成的。

谢谢

编辑: 感谢您的帮助,我尝试一下您提供给我的动态代码并收到此错误。

Msg 8167, Level 16, State 1, Line 1
The type of column "answer" conflicts with the type of other columns specified in the UNPIVOT list.

我的桌子是

RID         Question    Answer
4482515 Some Question1  Some Answer1
4482515 Some Question2  Some Answer2
4482515 Some Question3  Some Answer3
4484094 Some Question1  Answer1
4484094 Some Question2  Answer2
4484094 Some Question3  Answer3
4484094 Some Question4  Answer4

我打印出SQL,结果如下。

SELECT rid, [question1],[answer1],[question2],[answer2],[question3],[answer3],[question4],[answer4],[question5],[answer5],[question6],[answer6]
              from
              (
                select rid,
                  col+cast(rn as varchar(10)) col,
                  value
                from
                (
                  select rid, question, answer,
                    row_number() over(partition by rid order by rid, question) rn
                  from #tmp_question
                ) src
                unpivot
                (
                  value
                  for col in (question, answer)
                ) unpiv
              ) d
              pivot 
              (
                  max(value)
                  for col in ([question1],[answer1],[question2],[answer2],[question3],[answer3],[question4],[answer4],[question5],[answer5],[question6],[answer6])
              ) p 

我的原始 SQL 代码也在下面

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

select @cols = STUFF((SELECT ',' + QUOTENAME(c.col+cast(rn as varchar(10))) 
                    from 
                    (
                      select row_number() over(partition by rid 
                                               order by rid, question) rn
                      from #tmp_question
                    ) d
                    cross apply
                    (
                      select 'question' col, 1 sort union all select 'answer', 2
                    ) c
                    group by col, rn, sort
                    order by rn, sort
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT rid, ' + @cols + '
              from
              (
                select rid,
                  col+cast(rn as varchar(10)) col,
                  value
                from
                (
                  select rid, question, answer,
                    row_number() over(partition by rid order by rid, question) rn
                  from #tmp_question
                ) src
                unpivot
                (
                  value
                  for col in (question, answer)
                ) unpiv
              ) d
              pivot 
              (
                  max(value)
                  for col in (' + @cols + ')
              ) p '

--print @query
execute(@query);

等待您的帮助!

【问题讨论】:

    标签: sql sql-server tsql pivot


    【解决方案1】:

    有几种方法可以做到这一点。

    如果您有已知数量的问题/答案,那么您可以使用 row_number() 以及聚合函数和 CASE 表达式:

    select id,
      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,
      max(case when rn = 3 then question end) question3,
      max(case when rn = 3 then answer end) answer3
    from
    (
      select id, question, answer,
        row_number() over(partition by id order by id, question) rn
      from yt
    ) src
    group by id;
    

    SQL Fiddle with Demo

    另一个建议是同时使用 UNPIVOT 和 PIVOT 函数来获得结果。 UNPIVOT 将获取您的 questionanswer 列并将它们转换为多行。

    UNPIVOT 的基本语法是:

    select id,
      col+cast(rn as varchar(10)) col,
      value
    from
    (
      -- when you perform an unpivot the datatypes have to be the same. 
      -- you might have to cast the datatypes in this query
      select id, question, cast(answer as varchar(500)) answer,
        row_number() over(partition by id order by id, question) rn
      from yt
    ) src
    unpivot
    (
      value
      for col in (question, answer)
    ) unpiv;
    

    Demo。这给出了一个结果:

    |      ID |       COL |                                VALUE |
    --------------------------------------------------------------
    | 4482515 | question1 | I would like to be informed by mail. |
    | 4482515 |   answer1 |                                   No |
    | 4482515 | question2 |                    Plan to Purchase? |
    | 4482515 |   answer2 |                       Over 12 months |
    | 4482515 | question3 |                   Test Question Text |
    | 4482515 |   answer3 |                          some Answer |
    

    如您所见,我在初始子查询中添加了一个row_number() 值,以便您可以将每个答案与问题相关联。取消透视后,您可以使用 question/answer 与串联的行号值对新列名的结果进行透视。具有 PIVOT 语法的代码将是:

    select id, question1, answer1, question2, answer2,
      question3, answer3
    from
    (
      select id,
        col+cast(rn as varchar(10)) col,
        value
      from
      (
      -- when you perform an unpivot the datatypes have to be the same. 
      -- you might have to cast the datatypes in this query
        select id, question, cast(answer as varchar(500)) answer,
          row_number() over(partition by id order by id, question) rn
        from yt
      ) src
      unpivot
      (
        value
        for col in (question, answer)
      ) unpiv
    ) d
    pivot
    (
      max(value)
      for col in (question1, answer1, question2, answer2,
                  question3, answer3)
    ) piv;
    

    SQL Fiddle with Demo。现在在你的情况下,你说你将有一个动态数量的问题/答案。如果是这种情况,那么您将需要使用动态 SQL 来获取结果:

    DECLARE @cols AS NVARCHAR(MAX),
        @query  AS NVARCHAR(MAX)
    
    select @cols = STUFF((SELECT ',' + QUOTENAME(c.col+cast(rn as varchar(10))) 
                        from 
                        (
                          select row_number() over(partition by id 
                                                   order by id, question) rn
                          from yt
                        ) d
                        cross apply
                        (
                          select 'question' col, 1 sort union all select 'answer', 2
                        ) c
                        group by col, rn, sort
                        order by rn, sort
                FOR XML PATH(''), TYPE
                ).value('.', 'NVARCHAR(MAX)') 
            ,1,1,'')
    
    set @query = 'SELECT id, ' + @cols + '
                  from
                  (
                    select id,
                      col+cast(rn as varchar(10)) col,
                      value
                    from
                    (
                     -- when you perform an unpivot the datatypes have to be the same. 
                     -- you might have to cast the datatypes in this query
                      select id, question, cast(answer as varchar(500)) answer,
                        row_number() over(partition by id order by id, question) rn
                      from yt
                    ) src
                    unpivot
                    (
                      value
                      for col in (question, answer)
                    ) unpiv
                  ) d
                  pivot 
                  (
                      max(value)
                      for col in (' + @cols + ')
                  ) p '
    
    execute(@query);
    

    SQL Fiddle with Demo。这些给出了一个结果:

    |      ID |                            QUESTION1 | ANSWER1 |         QUESTION2 |        ANSWER2 |          QUESTION3 |     ANSWER3 |
    ------------------------------------------------------------------------------------------------------------------------------------
    | 4482515 | I would like to be informed by mail. |      No | Plan to Purchase? | Over 12 months | Test Question Text | some Answer |
    

    【讨论】:

    • @user2394918 如果您有问题或需要提供更多详细信息,请编辑您的原始帖子。请不要使用您的详细信息编辑此答案。
    • 老兄,编辑不是这样工作的。你编辑你的问题而不是答案来反映你的新细节。
    • 对不起,我是这个论坛的新手。请接受我的道歉。我现在编辑我的帖子,请帮助我
    • @user2394918 问题/答案列的数据类型是什么?它们需要具有相同的数据类型和长度。查看我的编辑。
    • 问题是 varchar(500),答案是 varchar(255)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-13
    • 2018-02-21
    • 1970-01-01
    • 1970-01-01
    • 2012-10-10
    • 2019-06-05
    • 1970-01-01
    相关资源
    最近更新 更多