sql >> Databáze >  >> RDS >> Sqlserver

Jednoduchý způsob, jak transponovat sloupce a řádky v SQL?

Existuje několik způsobů, jak můžete tato data transformovat. Ve svém původním příspěvku jste uvedli, že PIVOT se zdá být pro tento scénář příliš složitý, ale lze jej velmi snadno použít pomocí obou UNPIVOT a PIVOT funkce na serveru SQL Server.

Pokud však k těmto funkcím nemáte přístup, lze je replikovat pomocí UNION ALL UNPIVOT a poté agregační funkce s CASE příkaz PIVOT :

Vytvořit tabulku:

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 and CASE Version:

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

Viz SQL Fiddle with Demo

UNION ALL provede UNPIVOT dat transformací sloupců Paul, John, Tim, Eric do samostatných řad. Poté použijete agregační funkci sum() s case pro získání nových sloupců pro každou color .

Uvolnění a otočení statické verze:

Oba UNPIVOT a PIVOT funkce na SQL serveru tuto transformaci značně usnadňují. Pokud znáte všechny hodnoty, které chcete transformovat, můžete je napevno zakódovat do statické verze a získat výsledek:

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

Viz SQL Fiddle with Demo

Vnitřní dotaz s UNPIVOT provádí stejnou funkci jako UNION ALL . Vezme seznam sloupců a změní jej na řádky, PIVOT poté provede konečnou transformaci do sloupců.

Verze dynamického pivotu:

Pokud máte neznámý počet sloupců (Paul, John, Tim, Eric ve vašem příkladu) a poté neznámý počet barev k transformaci, můžete pomocí dynamického sql vygenerovat seznam a UNPIVOT a poté 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)

Viz SQL Fiddle with Demo

Dynamická verze se dotazuje jak yourtable a poté sys.columns tabulky pro vygenerování seznamu položek k UNPIVOT a PIVOT . To se pak přidá do řetězce dotazu, který se má provést. Výhodou dynamické verze je, že máte měnící se seznam colors a/nebo names toto vygeneruje seznam za běhu.

Všechny tři dotazy přinesou stejný výsledek:

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


  1. Jak funguje Trunc() v PostgreSQL

  2. Co je Microsoft Access a k čemu jej používáte?

  3. Jak může nastavení jazyka ovlivnit výsledky FORMAT() na serveru SQL (příklady T-SQL)

  4. MySql zobrazuje výkon