Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

SQL 2012 — Pivot i Unpivot

Możesz użyć dynamicznego SQL do transpozycji tabeli:

DECLARE @cols NVARCHAR(MAX) = 
                STUFF((SELECT DISTINCT ',' + QUOTENAME(CONCAT([Year], '_', [Month]))
                      FROM #tab
                      FOR XML PATH(''), TYPE
                     ).value('.', 'NVARCHAR(MAX)') 
                     , 1, 1, '');

DECLARE @query NVARCHAR(MAX) = 
FORMATMESSAGE(
N'SELECT col_name, customer, %s
FROM (SELECT [year_month] = CONCAT([Year], ''_'', [Month]),
             Customer, No_Trans, spend, points
      FROM #tab) AS sub
UNPIVOT
(
    val FOR col_name  IN (No_trans, spend, points)
) AS unpvt
PIVOT
(
    MAX(val) FOR [year_month] IN (%s)
) AS pvt
ORDER BY customer, col_name;', @cols, @cols); 

EXEC [dbo].[sp_executesql] @query;

LiveDemo

Wyjście:

╔══════════╦══════════╦════════╦════════╦════════╗
║   col    ║ customer ║ 2015_1 ║ 2015_2 ║ 2015_3 ║
╠══════════╬══════════╬════════╬════════╬════════╣
║ No_Trans ║        1 ║     30 ║     20 ║     10 ║
║ points   ║        1 ║     10 ║      5 ║     15 ║
║ spend    ║        1 ║    400 ║    150 ║    500 ║
║ No_Trans ║        2 ║      5 ║        ║        ║
║ points   ║        2 ║      7 ║        ║        ║
║ spend    ║        2 ║    100 ║        ║        ║
╚══════════╩══════════╩════════╩════════╩════════╝

Jeśli chcesz zeros na brakującej pozycji możesz użyć ISNULL/COALESCE . Pamiętaj, że nie każdy typ danych może zostać zastąpiony przez 0 (int)

LiveDemo2

EDYTUJ:

FORMATMESSAGE to wymyślny sposób na zastąpienie %s ze sznurkiem. Można to łatwo zmienić za pomocą prostego REPLACE :

 DECLARE @query NVARCHAR(MAX) = 
 N'SELECT col1, col2, <placeholder>
   FROM ...
   ...
   PIVOT( MAX(col) IN col2 IN (<placeholder>)
   ...';

 SET @query = REPLACE(@query, '<placeholder', @cols);

 -- for debug
 PRINT @query;

Jak to działa:

  1. Wygeneruj [year_month] kolumna w podzapytaniu
  2. UNPIVOT dane (kolumny do wiersza)
  3. PIVOT wynik (od wierszy do kolumn)
  4. Opakuj go dynamicznym SQL, aby umożliwić generowanie kolumn bez znajomości [year_month] z góry.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Skąd SqlCacheDependency wie, kiedy komunikować się z dowolnymi odbiornikami, gdy dane w tabeli ulegną zmianie?

  2. Jak połączyć dane z wielu wierszy w jeden?

  3. Jak WYBRAĆ * ale bez Nazwy kolumn muszą być unikalne w każdym widoku

  4. Zapytanie rekurencyjne SQL

  5. Nie można utworzyć parametrów połączenia dla zdalnego pulpitu dla aplikacji C#