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

Jak przekształcić dane z wierszy na podstawie określonej kolumny do innej struktury danych

Możesz użyć unpivot/pivot, aby uzyskać żądany wynik. Istnieje kilka różnych sposobów uzyskania wyniku, jeśli masz ograniczoną liczbę wartości, możesz na stałe zakodować zapytanie, ale jeśli masz nieznaną liczbę wartości, będziesz musiał użyć dynamicznego SQL.

Proces UNPIVOT skonwertuje wiele kolumn c1 itp. w wielu wierszach. Gdy dane znajdą się w wielu wierszach, możesz łatwo zastosować funkcję PIVOT. Możesz użyć funkcji unpivot lub CROSS APPLY, aby przekonwertować dane z wielu kolumn:

select id,
  col = 'Service'+Service+'_'+col+'_'+cast(seq as varchar(10)),
  value
from
(
  select id, service, c1, cn
    , row_number() over(partition by id
                        order by service) seq
  from yourtable
) t
cross apply
(
  select 'c1', c1 union all
  select 'cn', cn
) c (col, value)

Zobacz Skrzypce SQL z wersją demonstracyjną . Zastosowanie krzyżowe spowoduje konwersję danych do formatu:

| ID |           COL | VALUE |
|  1 | ServiceA_c1_1 |     5 |
|  1 | ServiceA_cn_1 |     3 |
|  1 | ServiceB_c1_2 |     2 |
|  1 | ServiceB_cn_2 |     1 |
|  2 | ServiceA_c1_1 |     9 |
|  2 | ServiceA_cn_1 |     4 |

Gdy dane będą w tym formacie, możesz zastosować PIVOT:

select id, ServiceA_c1_1, ServiceA_cn_1,
  ServiceB_c1_2, ServiceB_cn_2
from
(
  select id,
    col = 'Service'+Service+'_'+col+'_'+cast(seq as varchar(10)),
    value
  from
  (
    select id, service, c1, cn
      , row_number() over(partition by id
                          order by service) seq
    from yourtable
  ) t
  cross apply
  (
    select 'c1', c1 union all
    select 'cn', cn
  ) c (col, value)
) d
pivot
(
  max(value)
  for col in (ServiceA_c1_1, ServiceA_cn_1,
              ServiceB_c1_2, ServiceB_cn_2)
) piv;

Zobacz Skrzypce SQL z wersją demonstracyjną .

Następnie, jeśli masz nieznaną liczbę wartości, możesz przekonwertować powyższe zapytanie na dynamiczny SQL:

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

select @cols = STUFF((SELECT ',' + QUOTENAME('Service'+Service+'_'+col+'_'+cast(seq as varchar(10))) 
                    from 
                    (
                      select service, 
                        row_number() over(partition by id
                                          order by service) seq
                      from yourtable 
                    )d
                    cross apply
                    (
                      select 'c1', 1 union all
                      select 'cn', 2
                    ) c (col, so)
                    group by seq, Service, col, so
                    order by seq, so
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT id, ' + @cols + ' 
            from 
            (
              select id,
                col = ''Service''+Service+''_''+col+''_''+cast(seq as varchar(10)),
                value
              from
              (
                select id, service, c1, cn
                  , row_number() over(partition by id
                                      order by service) seq
                from yourtable
              ) t
              cross apply
              (
                select ''c1'', c1 union all
                select ''cn'', cn
              ) c (col, value)
            ) x
            pivot 
            (
                max(value)
                for col in (' + @cols + ')
            ) p '

execute sp_executesql @query;

Zobacz SQL Fiddle z wersją demonstracyjną . Oba dadzą wynik:

| ID | SERVICEA_C1_1 | SERVICEA_CN_1 | SERVICEB_C1_2 | SERVICEB_CN_2 |
|  1 |             5 |             3 |             2 |             1 |
|  2 |             9 |             4 |        (null) |        (null) |



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Błąd połączenia SQL:System.Data.SqlClient.SqlException (0x80131904)

  2. Jak uzyskać listę kolumn w tabeli lub widoku?

  3. Pole datownika automatycznej aktualizacji programu SQL Server

  4. SQL Server, połączenie LIKE i IN?

  5. Nie można połączyć się z bazą danych z pliku