sql >> Database teknologi >  >> RDS >> Sqlserver

Hvordan man transformerer data fra rækker baseret på en specifik kolonne til en anden datastruktur

Du kan bruge unpivot/pivot for at få det resultat, du ønsker. Der er et par forskellige måder, hvorpå du kan få resultatet, hvis du har et begrænset antal værdier, kan du hardkode forespørgslen, men hvis du har et ukendt antal værdier, skal du bruge dynamisk SQL.

UNPIVOT-processen vil konvertere de flere kolonner i c1 osv. i flere rækker. Når først data er i flere rækker, kan du nemt anvende PIVOT-funktionen. Du kan bruge unpivot-funktionen eller CROSS APPLY til at konvertere data fra flere kolonner:

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)
 

Se SQL Fiddle with Demo . Krydset anvende vil konvertere dine data til formatet:

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

Når dataene er i dette format, kan du anvende 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;
 

Se SQL Fiddle with Demo .

Så hvis du har et ukendt antal værdier, kan du konvertere ovenstående forespørgsel til dynamisk 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;
 

Se SQL Fiddle with Demo . Begge vil give et resultat:

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


  1. Aktiver SSL-understøttelse for pgsql

  2. vælg fra en tabel, indsæt i en anden tabel oracle sql-forespørgsel

  3. Hvordan laver man en SUM på tværs af to ikke-relaterede tabeller?

  4. Aktivering af to-faktor-godkendelse for ScaleGrid DBaaS