Data: 8.07.2021

MS SQL operatory pivot i unpivot
Spis treści
Za pomocą niestandardowych operatorów PIVOT i UNPIVOT w języku MS SQL możesz przestawić dane z kolumn w wiersze i odwrotnie.
MS SQL operatory pivot i unpivot – do czego służą?
Operatory PIVOT i UNPIVOT w SQL są najczęściej wykorzystywane w raportowaniu i przygotowywaniu danych do wizualizacji.
Operator PIVOT umożliwia przekształcenie wierszy w kolumny. Jest przydatny, gdy chcemy zgrupować dane i przedstawić je w układzie tabelarycznym np. możemy przedstawić listę miesięcznych przychodów w kolumnach odpowiadającym poszczególnym miesiącom.
UNPIVOT działa odwrotnie – przekształca kolumny w wiersze. Przykładowo, jeśli dla każdego miesiąca mamy oddzielną kolumnę, za pomocą operatora UNPIVOT możemy wszystkie miesiące umieścić w wierszach w jednej kolumnie i nadać jej nazwę Miesiąc.
Operator PIVOT
Operator PIVOT:
- przekształca dane z wierszy w kolumny
- grupuje dane i wywołuje dla każdej grupy wskazaną funkcję agregującą (grupującą).
W wyniku przekształcenia otrzymujemy zbiór danych, w których informacje zaprezentowane są na wzór tabel przestawnych z programu MS Excel.
Zapytanie do bazy danych. Odczytujemy informacje, na podstawie których zbudujemy operatorem PIVOT tabelę przestawną.
Use AdventureWorks2012;SELECT a.ProductID, YEAR(b.OrderDate) AS Rok, SUM(a.LineTotal) AS Sprzedaż FROM Sales.SalesOrderDetail a JOIN Sales.SalesOrderHeader b ON a.SalesOrderID = b. SalesOrderIDGROUP BY a.ProductID, YEAR(b.OrderDate)ORDER BY a.ProductID, YEAR(b.OrderDate);Wynik zapytania:
| ProductID | Rok | Sprzedaż | |
|---|---|---|---|
| 7 | 708 | 2007 | 69582.321245 |
| 8 | 708 | 2008 | 59739.956063 |
| 9 | 709 | 2005 | 3057.689950 |
| 10 | 709 | 2006 | 3002.698250 |
| 11 | 710 | 2005 | 376.200000 |
| 12 | 710 | 2006 | 136.800000 |
| 13 | 711 | 2005 | 7114.139608 |
| 14 | 711 | 2006 | 26446.253982 |
| 15 | 711 | 2007 | 69660.441903 |
W wyniku zapytania grupy (ProductID) i podgrupy (Rok) oraz wyliczone dla nich sumy (Sprzedaż) wyświetlone są w kolejnych wierszach.
Za pomocą operatora PIVOT możemy przedstawić dane w formie tabeli przestawnej. Produkty (ProductID) przedstawimy w wierszach a lata (Rok) w kolumnach. Na przecięciu wiersza i kolumny umieścimy sumę sprzedaży danego produktu w poszczególnych latach. Prezentacja danych w ten sposób ułatwi ich odczytanie i analizę.
Odczytane dane zapisujemy do tymczasowej tabeli o nazwie #tab_przestawna
Use AdventureWorks2012;SELECT a.ProductID, YEAR(b.OrderDate) AS Rok, SUM(a.LineTotal) AS SprzedażINTO #tab_przestawna FROM Sales.SalesOrderDetail a JOIN Sales.SalesOrderHeader b ON a.SalesOrderID = b. SalesOrderIDGROUP BY a.ProductID, YEAR(b.OrderDate)ORDER BY a.ProductID, YEAR(b.OrderDate);Uwaga! Tabele tymczasowe poprzedzone jednym znakiem # lub dwoma znakami ## nie są fizycznie zapisywane w bazie danych. Dostępne są one tylko w trakcie trwania sesji SSMS (SQL Server Management Studio).
- #nazwa_tabeli – tabele lokalne – widoczne tylko w ramach jednej aktywnej sesji
- ##nazwa_tabeli – tabele globalne – widoczne w ramach wszystkich aktywnych sesji.

Tabela tymczasowa o nazwie #tab_przestawna widoczna będzie tylko w sesji numer 1 (w tej, w której została utworzona).

Tabela tymczasowa o nazwie ##tab_przestawna widoczna będzie w sesji numer 1, 2.
Jeżeli do utworzenia raportu tabeli przestawnej użyjemy tabeli tymczasowej #tab_przestawna, wszystkie zapytania musimy uruchomić po kolei, w ramach tej samej sesji, w której utworzona została tabela tymczasowa #tab_przestawna.
Przekształcanie wierszy na kolumny przebiega w następujących etapach:
- pogrupowanie danych według wartości tej kolumny, która będzie zawierała nagłówki wierszy. W przykładzie jest to kolumna ProductID. Następuje tutaj niejawne grupowanie, gdyż nazwa kolumny ProductID nie pojawia się na liście parametrów operatora PIVOT.
- przekształcenie nagłówków kolumn – do utworzonych kolejnych kolumn kopiowane są dane ze wskazanej kolumny tabeli. W przykładzie dane z kolumny LineTotal.
- wywołanie dla każdego pola utworzonej tabeli funkcji grupującej. W przykładzie jest to funkcja SUM(), za pomocą której sumujemy i grupujemy dane z kolumny LineTotal.
Use AdventureWorks2012;SELECT P.ProductID, [2005], [2006],[2007], [2008]FROM #tab_przestawnaPIVOT (SUM(Sprzedaż)FOR Rok IN ([2005], [2006],[2007], [2008]) ) AS PORDER BY P.ProductID;W powyższym zapytaniu:
- w klauzuli SELECT definiujemy listę kolumn tabeli przestawnej: pierwsza kolumna zawiera identyfikatory produktów, kolejne kolumny zawierają sumę sprzedaży w poszczególnych latach. Lista kolumn [2005], [2006],[2007], [2008] wpisana została ręcznie.
- za pomocą operatora PIVOT określamy:
- funkcję grupującą – w naszym przykładzie jest to funkcja SUM()
- kolumnę, z której dane będą sumowane – w naszym przykładzie jest to kolumna Sprzedaż
- kolumnę bazową, z której odczytane zostaną dane do umieszczenia w kolumnach [2005], [2006],[2007], [2008]. W naszym przykładzie jest to Rok
- kolumny ProductID używamy do pogrupowania danych. Kolejne wiersze wyniku zapytania zawierają informacje o sprzedaży poszczególnych produktów.
Wynik zapytania – tabela przestawna
| ProductID | 2005 | 2006 | 2007 | 2008 | |
|---|---|---|---|---|---|
| 1 | 707 | 6439.493500 | 22969.627428 | 66784.431947 | 61578.841517 |
| 2 | 708 | 6681.731500 | 24865.509028 | 69582.321245 | 59739.956063 |
| 3 | 709 | 3057.689950 | 3002.698250 | NULL | NULL |
| 4 | 710 | 376.200000 | 136.800000 | NULL | NULL |
| 5 | 711 | 7114.139608 | 26446.253982 | 69660.441903 | 62185.781556 |
Tablę tymczasową, użytą do tworzenia tabeli przestawnej, można zamienić na podzapytanie.
Use AdventureWorks2012;SELECT P.ProductID, [2005], [2006],[2007], [2008]FROM (SELECT a.ProductID, YEAR(b.OrderDate) AS Rok, SUM(a.LineTotal) AS Sprzedaż FROM Sales.SalesOrderDetail a JOIN Sales.SalesOrderHeader b ON a.SalesOrderID = b. SalesOrderID GROUP BY a.ProductID, YEAR(b.orderdate) ) aPIVOT (SUM(Sprzedaż)FOR Rok IN ([2005], [2006],[2007], [2008]) ) AS PORDER BY P.ProductID;Informacje na temat podzapytań znajdziesz w artykule pod linkiem MS SQL – podzapytania.
Operator UNPIVOT
Działanie operatora UNPIVOT polega na odwróceniu wyniku działania operatora PIVOT. Za jego pomocą zamieniamy kolumny na wiersze i rozbijamy niejawnie utworzone grupy w tabeli przestawnej.
Tworzymy tabelę przestawną i wynik zapisujemy do tabeli tymczasowej o nazwie #tab_pivot
Use AdventureWorks2012;SELECT a.ProductID, [2005], [2006],[2007], [2008]INTO #tab_pivotFROM #tab_przestawna PIVOT ( SUM(Sprzedaż) FOR Rok IN ([2005], [2006],[2007], [2008]) ) AS a ORDER BY a.ProductID;Dane z tabeli tymczasowej #tab_pivot możemy odczytać za pomocą poniższego polecenia:
Use AdventureWorks2012;SELECT *FROM #tab_pivotPrzekształcenie kolumn na wiersze, za pomocą operatora UNPIVOT, przebiega w następujących etapach:
- wygenerowanie duplikatów wartości kolumny wskazanej w bloku IN
- utworzenie kolumny o nazwie wskazanej w bloku FOR
- usunięcie z wyniku wartości specjalnej NULL. Usunięcie wartości NULL powoduje, że operatory PIVOT i UNPIVOT są niesymetryczne. Po przekształceniu wierszy na kolumny a następnie kolumn na wiersze wynik zapytania może zawierać mniej danych.
SELECT a.ProductID, a.Rok, a.SprzedażFROM #tab_pivotUNPIVOT (Sprzedaż FOR Rok IN ([2005], [2006], [2007], [2008])) AS a;W powyższym zapytaniu:
- w klauzuli SELECT definiujemy listę kolumn wyniku
- w klauzuli FROM wskazujemy tabelę źródłową
- za pomocą operatora UNPIVOT definiujemy kolumnę, w której zostaną umieszczone odczytane z tabeli przestawnej podsumowania (kolumna Sprzedaż), oraz określamy kolumnę, w której zostaną umieszczone nagłówki kolumn tabeli przestawnej (kolumna Rok)
Wynik zapytania:
| ProductID | Rok | Sprzedaż | |
|---|---|---|---|
| 4 | 707 | 2008 | 61578.841517 |
| 5 | 708 | 2005 | 6681.731500 |
| 6 | 708 | 2006 | 24865.509028 |
| 7 | 708 | 2007 | 69582.321245 |
| 8 | 708 | 2008 | 59739.956063 |
| 9 | 709 | 2005 | 3057.689950 |
| 10 | 709 | 2006 | 3002.698250 |
| 11 | 710 | 2005 | 376.200000 |
| 12 | 710 | 2006 | 136.800000 |
| 13 | 711 | 2005 | 7114.139608 |
| 14 | 711 | 2006 | 26446.253982 |
Zachęcamy do udziału w naszym kursie SQL poziom średnio-zaawansowany, na którym przećwiczysz w praktyce m.in. operatory PIVOT i UNPIVOT.
