Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

SQL Server:Pivot z niestandardowymi nazwami kolumn

Możesz to zrobić na kilka sposobów.

Jeśli masz znaną liczbę pytań/odpowiedzi, możesz użyć row_number() wraz z funkcją agregującą i wyrażeniem 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;

Zobacz Skrzypce SQL z wersją demonstracyjną

Inną sugestią byłoby użycie zarówno funkcji UNPIVOT, jak i funkcji PIVOT, aby uzyskać wynik. UNPIVOT odpowie na Twoje question i answer kolumny i przekonwertuj je na wiele wierszy.

Podstawowa składnia UNPIVOT to:

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;

Zobacz Demo . Daje to wynik:

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

Jak widać, dodałem row_number() wartość do początkowego podzapytania, dzięki czemu można powiązać każdą odpowiedź z pytaniem. Po przestawieniu wyniku możesz przestawić wynik na nowe nazwy kolumn za pomocą question /answer o połączonej wartości numeru wiersza. Kod ze składnią PIVOT będzie wyglądał następująco:

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;

Zobacz SQL Fiddle z wersją demonstracyjną . Teraz w swojej sytuacji stwierdziłeś, że będziesz miał dynamiczną liczbę pytań/odpowiedzi. Jeśli tak jest, będziesz musiał użyć dynamicznego SQL, aby uzyskać wynik:

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

Zobacz Skrzypce SQL z wersją demonstracyjną . Dają one wynik:

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



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak obsługiwać wiele obiektów za pomocą okna szczegółów Eksploratora obiektów w SSMS — samouczek SQL Server / TSQL, część 22

  2. MultipleActiveResultSets=Prawda czy wiele połączeń?

  3. Zwróć listę tabel i widoków w SQL Server przy użyciu T-SQL (sp_tables)

  4. Obcinanie VARCHAR(MAX) SQLAlchemy

  5. Używanie TSQL do rozpakowywania wartości