sql >> Database >  >> RDS >> Sqlserver

Eenvoudige manier om kolommen en rijen in SQL te transponeren?

Er zijn verschillende manieren waarop u deze gegevens kunt transformeren. In je oorspronkelijke bericht verklaarde je dat PIVOT lijkt te complex voor dit scenario, maar het kan heel gemakkelijk worden toegepast met zowel de UNPIVOT en PIVOT functies in SQL Server.

Als u echter geen toegang heeft tot deze functies, kan dit worden gerepliceerd met UNION ALL naar UNPIVOT en dan een aggregatiefunctie met een CASE statement naar PIVOT :

Tafel maken:

CREATE TABLE yourTable([color] varchar(5), [Paul] int, [John] int, [Tim] int, [Eric] int);

INSERT INTO yourTable
    ([color], [Paul], [John], [Tim], [Eric])
VALUES
    ('Red', 1, 5, 1, 3),
    ('Green', 8, 4, 3, 5),
    ('Blue', 2, 2, 9, 1);

Union All, Aggregate en CASE-versie:

select name,
  sum(case when color = 'Red' then value else 0 end) Red,
  sum(case when color = 'Green' then value else 0 end) Green,
  sum(case when color = 'Blue' then value else 0 end) Blue
from
(
  select color, Paul value, 'Paul' name
  from yourTable
  union all
  select color, John value, 'John' name
  from yourTable
  union all
  select color, Tim value, 'Tim' name
  from yourTable
  union all
  select color, Eric value, 'Eric' name
  from yourTable
) src
group by name

Zie SQL Fiddle met demo

De UNION ALL voert de UNPIVOT . uit van de gegevens door de kolommen Paul, John, Tim, Eric . te transformeren in aparte rijen. Dan pas je de aggregatiefunctie sum() . toe met de case statement om de nieuwe kolommen voor elke color te krijgen .

Ongedaan maken van draaien en draaien van statische versie:

Zowel de UNPIVOT en PIVOT functies in de SQL-server maken deze transformatie veel gemakkelijker. Als u alle waarden kent die u wilt transformeren, kunt u ze hardcoderen in een statische versie om het resultaat te krijgen:

select name, [Red], [Green], [Blue]
from
(
  select color, name, value
  from yourtable
  unpivot
  (
    value for name in (Paul, John, Tim, Eric)
  ) unpiv
) src
pivot
(
  sum(value)
  for color in ([Red], [Green], [Blue])
) piv

Zie SQL Fiddle met demo

De innerlijke vraag met de UNPIVOT vervult dezelfde functie als de UNION ALL . Het neemt de lijst met kolommen en verandert het in rijen, de PIVOT voert vervolgens de laatste transformatie in kolommen uit.

Dynamische draaiversie:

Als u een onbekend aantal kolommen heeft (Paul, John, Tim, Eric in uw voorbeeld) en vervolgens een onbekend aantal kleuren om te transformeren, kunt u dynamische sql gebruiken om de lijst te genereren naar UNPIVOT en dan PIVOT :

DECLARE @colsUnpivot AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX),
    @colsPivot as  NVARCHAR(MAX)

select @colsUnpivot = stuff((select ','+quotename(C.name)
         from sys.columns as C
         where C.object_id = object_id('yourtable') and
               C.name <> 'color'
         for xml path('')), 1, 1, '')

select @colsPivot = STUFF((SELECT  ',' 
                      + quotename(color)
                    from yourtable t
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query 
  = 'select name, '[email protected]+'
      from
      (
        select color, name, value
        from yourtable
        unpivot
        (
          value for name in ('[email protected]+')
        ) unpiv
      ) src
      pivot
      (
        sum(value)
        for color in ('[email protected]+')
      ) piv'

exec(@query)

Zie SQL Fiddle met demo

De dynamische versie bevraagt ​​zowel yourtable en dan de sys.columns tabel om de lijst met items te genereren voor UNPIVOT en PIVOT . Dit wordt vervolgens toegevoegd aan een uit te voeren queryreeks. Het voordeel van de dynamische versie is als je een wisselende lijst met colors hebt en/of names dit zal de lijst tijdens runtime genereren.

Alle drie de zoekopdrachten zullen hetzelfde resultaat opleveren:

| NAME | RED | GREEN | BLUE |
-----------------------------
| Eric |   3 |     5 |    1 |
| John |   5 |     4 |    2 |
| Paul |   1 |     8 |    2 |
|  Tim |   1 |     3 |    9 |


  1. Precisie van numerieke kolom wijzigen in Oracle

  2. SQL-referentietabel:basisquery's maken en schrijven

  3. Hoe Tan() werkt in PostgreSQL

  4. Verbindingsreeksparameters voor opgeslagen specificaties