sql >> Database >  >> RDS >> Sqlserver

Gegevens transformeren van rijen op basis van een specifieke kolom naar een andere gegevensstructuur

U kunt de unpivot/pivot gebruiken om het gewenste resultaat te krijgen. Er zijn een paar verschillende manieren waarop u het resultaat kunt krijgen. Als u een beperkt aantal waarden heeft, kunt u de query hard coderen, maar als u een onbekend aantal waarden heeft, moet u dynamische SQL gebruiken.

Het UNPIVOT-proces converteert de meerdere kolommen van c1 , etc` in meerdere rijen. Zodra de gegevens in de meerdere rijen staan, kunt u eenvoudig de PIVOT-functie toepassen. U kunt de unpivot-functie of CROSS APPLY gebruiken om de gegevens uit meerdere kolommen te converteren:

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)

Zie SQL Fiddle met demo . De kruistoepassing zet uw gegevens om in het formaat:

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

Zodra de gegevens in dit formaat zijn, kunt u PIVOT toepassen:

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;

Zie SQL Fiddle met demo .

Als u een onbekend aantal waarden heeft, kunt u de bovenstaande query converteren naar dynamische 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;

Zie SQL Fiddle met demo . Beide geven een resultaat:

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



  1. MySQL-opgeslagen procedure met IF/THEN/ELSE

  2. FOUT krijgen:er is een fout opgetreden in de opdracht met exit-status 1:bij het installeren van mysql

  3. mysql - toon 2 aparte providernaam uit 1 providertabel

  4. mysql regexp geeft boolean terug in plaats van waarde