Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

SQL Server:Pivot mit benutzerdefinierten Spaltennamen

Es gibt einige Möglichkeiten, wie Sie dies tun können.

Wenn Sie eine bekannte Anzahl von Fragen/Antworten hätten, könnten Sie row_number() verwenden zusammen mit einer Aggregatfunktion und einem CASE-Ausdruck:

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;

Siehe SQL Fiddle mit Demo

Ein weiterer Vorschlag wäre, sowohl die UNPIVOT- als auch die PIVOT-Funktion zu verwenden, um das Ergebnis zu erhalten. Das UNPIVOT wird Ihre question entgegennehmen und answer Spalten und konvertieren Sie sie in mehrere Zeilen.

Die grundlegende Syntax für UNPIVOT lautet:

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;

Siehe Demo . Dies ergibt ein Ergebnis:

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

Wie Sie sehen können, habe ich eine row_number() hinzugefügt Wert der anfänglichen Unterabfrage hinzufügen, damit Sie jede Antwort der Frage zuordnen können. Nachdem die Pivotierung aufgehoben wurde, können Sie das Ergebnis mit der question auf die neuen Spaltennamen pivotieren /answer mit dem verketteten Zeilennummernwert. Der Code mit der PIVOT-Syntax lautet:

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;

Siehe SQL-Geige mit Demo . In Ihrer Situation haben Sie angegeben, dass Sie eine dynamische Anzahl von Fragen/Antworten haben werden. Wenn dies der Fall ist, müssen Sie dynamisches SQL verwenden, um das Ergebnis zu erhalten:

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

Siehe SQL Fiddle mit Demo . Diese geben ein Ergebnis:

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