Pivotoperatoren i SQL Server konverterer hver række i det aggregerede resultatsæt til tilsvarende kolonner i outputsættet. Pivotoperatoren er især nyttig til at skrive krydstabuleringsforespørgsler.
Lad os tage et kig på, hvordan det fungerer i praksis.
Forberedelse af data
Lad os først oprette nogle dummy-data, som vi derefter kan bruge til at implementere pivotoperatoren.
CREATE DATABASE schooldb
CREATE TABLE student
(
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
gender VARCHAR(50) NOT NULL,
DOB datetime NOT NULL,
total_score INT NOT NULL,
city VARCHAR(50) NOT NULL
)
INSERT INTO student
VALUES (1, 'Jolly', 'Female', '12-JUN-1989', 500, 'London'),
(2, 'Jon', 'Male', '02-FEB-1974', 545, 'Manchester'),
(3, 'Sara', 'Female', '07-MAR-1988', 600, 'Leeds'),
(4, 'Laura', 'Female', '22-DEC-1981', 400, 'Liverpool'),
(5, 'Alan', 'Male', '29-JUL-1993', 500, 'London'),
(6, 'Kate', 'Female', '03-JAN-1985', 500, 'Liverpool'),
(7, 'Joseph', 'Male', '09-APR-1982', 643, 'London'),
(8, 'Mice', 'Male', '16-AUG-1974', 543, 'Liverpool'),
(9, 'Wise', 'Male', '11-NOV-1987', 499, 'Manchester'),
(10, 'Elis', 'Female', '28-OCT-1990', 400, 'Leeds');
Hvordan virker pivotoperatøren?
Standardmåden til at gruppere SQL-data er ved at bruge Group By-klausulen. Lad os oprette en forespørgsel, der beregner gennemsnittet af værdierne i kolonnen total_score i elevtabellen, grupperet efter by.
USE schooldb
SELECT
city,
AVG(total_score) as Avg_Score
FROM
student
GROUP BY
city
Dette giver følgende resultat:
[tabel id=25 /]
Hvad hvis vi ønsker et resultatsæt, hvor bynavnene vises i kolonner, hvor hver kolonne indeholder gennemsnitsværdien af total_score for de elever, der tilhører den by? Noget som dette:
[tabel id=26 /]
Det er her, pivotoperatøren er praktisk.
Valg af basisdata
Det første trin, når du bruger pivotoperatoren, er at vælge de basisdata, som pivotoperatoren vil være baseret på. Vi ønsker at gruppere vores data efter by og finde gennemsnittet af total_score for de elever, der tilhører den by. Derfor skal vi skrive en simpel SELECT-sætning, der vælger byen og total_score.
SELECT
city,
total_score
FROM
student
Oprettelse af et midlertidigt datasæt
Nu, ideelt set, ville vi være i stand til direkte at anvende pivotoperatoren på de basisdata, som vi oprettede i det foregående afsnit, men det kan vi desværre ikke. For at pivot-operatoren skal fungere, skal vi lave et tabelværdi-udtryk, som vi kan anvende pivot-operatoren på. Vi har en række valgmuligheder her; vi kunne bruge afledte tabeller, almindelige tabeludtryk (CTE'er), eller vi kunne endda oprette midlertidige tabeller.
Til dette eksempel vil vi bruge en hurtig, enkel afledt tabel. For at gøre det med den grundlæggende select-sætning, som vi oprettede i sidste afsnit, pakker vi den ind i et sæt parenteser og anvender derefter et alias til den. Til sidst vælger vi alt fra den afledte tabel.
SELECT * FROM
(SELECT
city,
total_score
FROM
student
)
AS StudentTable
Anvendelse af pivotoperatøren
Nu hvor vi har forberedt vores basisdata og har oprettet en afledt tabel, vil vi anvende pivotoperatoren på den.
For at gøre dette skal du indsætte "PIVOT" i slutningen af den afledte tabel, efterfulgt af et sæt parenteser, og give denne pivottabel et alias.
Inde i parentesen skal vi angive nogle vigtige oplysninger.
- Vi skal angive det felt, vi vil anvende en aggregeret funktion på. I vores tilfælde ønsker vi at anvende AVG-aggregatfunktionen i kolonnen "total_score".
- Vi skal så sige, hvilke kolonner fra basisdataene vi pivoterer vores data til. Det gør vi ved at skrive "FOR" efterfulgt af kolonnenavnet, som er en by i vores eksempel.
- Det sidste trin er lidt irriterende. Vi skal angive de værdier fra bykolonnen, som vi ønsker skal blive overskrifter i vores pivottabel. Vi bruger IN-operatoren efterfulgt af et sæt parenteser. Inde i parentesen bruger vi en kommasepareret liste, hvor vi skriver navnet på hver kolonne inden for en firkantet parentes. I vores eksempel ønsker vi London, Leeds og Manchester som overskriftsnavne på pivottabellen, og derfor skriver vi dem i dette format:([London], [Leeds], [Manchester]).
USE schooldb
SELECT * FROM
(SELECT
city,
total_score
FROM
student
)
AS StudentTable
PIVOT(
AVG(total_score)
FOR city IN ([London],[Liverpool],[Leeds],[Manchester])
) AS StudentPivotTable
Hvis du udfører ovenstående forespørgsel, vil resultaterne se sådan ud:
[tabel id=27 /]
Tilføjelse af rækkegrupper i pivottabel
I de foregående afsnit så vi, hvordan man konverterer rækkegrupper til kolonnegrupper ved hjælp af pivotoperator. Du kan dog også tilføje rækkegrupper sammen med kolonnegrupper til en pivottabel.
For eksempel, hvis du vil finde gennemsnitsværdien af kolonnen total_score for alle elever grupperet efter by såvel som efter køn, kan du bruge kolonnegruppen og rækkegruppen sammen inde i en pivottabel. Her vil hver kolonne repræsentere et bynavn, og hver række vil repræsentere et elevkøn.
Heldigvis behøver du ikke skrive noget ekstra script for at tilføje rækkegrupper til en pivottabel. Inde i basisdatasættet skal du blot tilføje kolonnenavnet, som du vil tilføje som en rækkegruppe til pivottabellen.
USE schooldb
SELECT * FROM
(SELECT
city,
gender,
total_score
FROM
student
)
AS StudentTable
PIVOT(
AVG(total_score)
FOR city IN ([London],[Liverpool],[Leeds],[Manchester])
) AS StudentPivotTable
I ovenstående script tilføjede vi simpelthen "køn"-kolonnen i basis SELECT-sætningen.
Outputtet af ovenstående forespørgsel ser sådan ud:
[tabel id=28 /]
Dette er krydstabulering. For eksempel kan det ses af resultaterne, at den gennemsnitlige total_score af kvindelige studerende, der bor i London, er 500. På samme måde er den gennemsnitlige samlede score for mandlige studerende, der bor i London, 571.
Læs også:
Oprettelse af dynamisk pivottabel med funktionen QUOTENAME