sql >> Databasteknik >  >> RDS >> Sqlserver

Enkelt sätt att överföra kolumner och rader i SQL?

Det finns flera sätt att omvandla denna data. I ditt ursprungliga inlägg angav du att PIVOT verkar för komplicerat för detta scenario, men det kan appliceras mycket enkelt med både UNPIVOT och PIVOT funktioner i SQL Server.

Men om du inte har tillgång till dessa funktioner kan detta replikeras med UNION ALL till UNPIVOT och sedan en aggregerad funktion med en CASE uttalande till PIVOT :

Skapa tabell:

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

Se SQL Fiddle with Demo

UNION ALL utför UNPIVOT av data genom att transformera kolumnerna Paul, John, Tim, Eric i separata rader. Sedan tillämpar du aggregatfunktionen sum() med case för att få de nya kolumnerna för varje color .

Unpivot och Pivot Static Version:

Både UNPIVOT och PIVOT funktioner i SQL server gör denna transformation mycket enklare. Om du känner till alla värden som du vill omvandla kan du hårdkoda dem till en statisk version för att få resultatet:

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

Se SQL Fiddle with Demo

Den inre frågan med UNPIVOT utför samma funktion som UNION ALL . Den tar listan med kolumner och gör om den till rader, PIVOT utför sedan den slutliga omvandlingen till kolumner.

Dynamisk pivotversion:

Om du har ett okänt antal kolumner (Paul, John, Tim, Eric i ditt exempel) och sedan ett okänt antal färger att transformera kan du använda dynamisk sql för att generera listan till UNPIVOT och sedan 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)

Se SQL Fiddle with Demo

Den dynamiska versionen frågar både yourtable och sedan sys.columns tabell för att generera listan över objekt till UNPIVOT och PIVOT . Detta läggs sedan till i en frågesträng som ska köras. Plusen med den dynamiska versionen är om du har en föränderlig lista med colors och/eller names detta genererar listan vid körning.

Alla tre frågorna ger samma resultat:

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


  1. Hur SQLite Upper() fungerar

  2. Hur man använder flera databaser dynamiskt för en modell i CakePHP

  3. Gå med oss ​​för Microsoft Access med SQL Server Academy del II

  4. PL/pgSQL kolumnnamn samma som variabel