0

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

当前格式

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);

等待您的热心帮助!

4

1 回答 1

6

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

如果您有已知数量的问题/答案,则可以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

另一个建议是同时使用 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;

请参阅演示。这给出了一个结果:

|      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 |
于 2013-05-17T17:54:01.003 回答