sql >> Database teknologi >  >> RDS >> Database

Oprettelse af dynamisk pivottabel med funktionen QUOTENAME

I min tidligere artikel om den grundlæggende pivotoperator så vi, hvordan pivotoperatoren kunne bruges til at konvertere rækker til kolonner, hvilket resulterede i pivottabeller. Vi så, at der var tre hovedtrin til at oprette en pivottabel. Det første trin var at vælge basisdataene. Det andet trin var at konvertere basisdataene til et tabelværdiudtryk, og det sidste trin involverede at anvende en pivotoperator på de midlertidige data, hvilket resulterede i pivottabellen.

Tag et kig på eksemplet nedenfor.

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

Bemærk: For at oprette dummy-databasen og data, se den forrige artikel om Pivot-operatøren.

Begrænsninger for pivotoperatør

Der er dog visse begrænsninger for pivotoperatør. Inde i pivotoperatoren skal vi angive det samlede felt og de kolonner, som vi vil pivotere vores data på. Til sidst skal vi også indstille de individuelle værdier for de kolonneoverskrifter, vi ønsker at oprette.

Hvis vi udførte scriptet fra det forrige afsnit, ville vi få følgende resultat:

[tabel id=35 /]

Overskrifterne på kolonnerne er de individuelle værdier inde i bykolonnen. Vi specificerede disse værdier i pivotoperatoren i vores forespørgsel.

Den mest kedelige del af at oprette pivottabeller er at specificere værdierne for kolonneoverskrifterne manuelt. Dette er den del, der er udsat for de fleste fejl, især hvis dataene i din onlinedatakilde ændres. Vi kan ikke være sikre på, at de værdier, vi har angivet i pivotoperatoren, forbliver i databasen, indtil vi opretter denne pivottabel næste gang.

For eksempel har vi i vores manuskript specificeret London, Liverpool, Leeds og Manchester som værdier for overskrifter i vores pivottabel. Disse værdier fandtes i kolonnen By i elevtabellen. Hvad hvis en eller flere af disse værdier på en eller anden måde slettes eller opdateres? I sådanne tilfælde vil null blive returneret.

En bedre tilgang ville være at oprette en dynamisk forespørgsel, der returnerer et komplet sæt værdier fra den kolonne, hvorfra du forsøger at generere din pivottabel.

Oprettelse af en dynamisk pivottabel

I dette afsnit vil vi se, hvordan du opretter en dynamisk pivottabel.

Det betyder, at vi ikke manuelt skal angive værdierne for den kolonne, hvorfra vi forsøger at generere vores pivottabel. I stedet vil vi indstille disse værdier dynamisk. Til dette formål vil vi bruge funktionen "QUOTENAME".

Som altid skal du sikre dig, at du er godt sikkerhedskopieret, før du eksperimenterer med en ny kode. Se denne artikel om sikkerhedskopiering af MS SQL-databaser, hvis du ikke er sikker.

QUOTENAME-funktion

Funktionen "QUOTENAME" formaterer udvalgte resultater. Før du forklarer dynamisk pivot, er det værd at se på et hurtigt fungerende eksempel på "QUOTENAME"-funktionen.

Tag et kig på følgende forespørgsel.

USE schooldb

SELECT QUOTENAME(city)+ ','
FROM student

Som standard ombryder funktionen "QUOTENAME" de valgte elementer med firkantede parenteser. Outputtet af ovenstående forespørgsel ser sådan ud:

[tabel id=36 /]

Lagring af kolonnenavne i en variabel

Selvom vi har pakket kolonneværdierne med firkantede parenteser, skal vi angive værdierne i pivotoperatoren i dette format:

"[Leeds],[Liverpool],[London],[Manchester]"

For at gøre dette skal vi bruge en variabel.

USE schooldb

DECLARE @CityNames NVARCHAR(MAX) = ''

SELECT  @CityNames +=   QUOTENAME(city)+ ','
FROM 
(
	SELECT DISTINCT city
	FROM student
) AS CITIES

PRINT @CityNames

I ovenstående forespørgsel erklærede vi en variabel "@CityNames" og initialiserede den med en tom streng. Derefter brugte vi en SELECT-sætning til at vælge forskellige bynavne fra bykolonnen og gemme dem iterativt i variablen "@CityNames". I hver iteration vil en særskilt værdi i bykolonnen sammen med et komma blive tilføjet til variablen "@CityNames".

Derefter udskrev vi værdien gemt i denne variabel. Resultatet af ovenstående forespørgsel vil se således ud:

"[Leeds],[Liverpool],[London],[Manchester],,"

Hvis du ser på outputtet, er der et komma efter den sidste værdi. Det har vi ikke brug for.

Fjernelse af et efterfølgende komma

For at fjerne et efterfølgende komma, vil vi bruge en VENSTRE funktion, der tager en streng som sit første argument. Det andet argument er antallet af tegn, der skal returneres fra den streng startende fra det første tegn. Tag et kig på følgende forespørgsel:

USE schooldb

DECLARE @CityNames NVARCHAR(MAX) = ''

SELECT  @CityNames +=   QUOTENAME(city)+ ','
FROM 
(
	SELECT DISTINCT city
	FROM student
) AS CITIES

SET @CityNames = LEFT(@CityNames, LEN(@CityNames)-1)

PRINT @CityNames

Vær opmærksom på denne linje i scriptet:

SET @CityNames = LEFT(@CityNames, LEN(@CityNames)-1)

I denne linje i scriptet brugte vi funktionen VENSTRE til at få alle tegnene på venstre side af værdien gemt i "@CityNames"-variablen, startende fra det første element. I det andet argument brugte vi LEN-funktionen til at beregne antallet af værdielementer gemt i funktionen "@CityNames", og til sidst trak vi 1 fra den. Dette fjerner det efterfølgende komma fra strengen. Outputtet vil se sådan ud:

[Leeds],[Liverpool],[London],[Manchester]

Konvertering af SQL-forespørgsel til streng

Nu kan vi forhåbentlig bruge "@CityNames"-variablen inde i vores pivot-operator sådan her:

PIVOT(
	AVG(total_score)
	FOR city IN ( @CityNames )

Vi kan dog ikke bruge en variabel inde i vores pivotoperator. Den alternative tilgang er at konvertere vores komplette SQL-forespørgsel til en streng. Inde i denne streng kobler vi vores "@CityNames"-variabel.

USE schooldb

DECLARE @CityNames NVARCHAR(MAX) = ''
DECLARE @Query NVARCHAR(MAX) = '' 

SELECT  @CityNames +=   QUOTENAME(city)+ ','
FROM 
(
	SELECT DISTINCT city
	FROM student
) AS CITIES

SET @CityNames = LEFT(@CityNames, LEN(@CityNames)-1)

SET @Query =
'SELECT * FROM

(SELECT 
	city,
	total_score
FROM 
	student
)
AS StudentTable
PIVOT(
	AVG(total_score)
	FOR city IN (' + @CityNames +')
) AS StudentPivotTable'

PRINT @Query

Her erklærede vi en variabel "@Query" og gemte vores SQL-forespørgsel i denne variabel. Inde i pivot-operatoren sammenkædede vi værdien, der er gemt i variablen "@CityNames". For at se, hvordan den udførte forespørgsel ser ud, har vi udskrevet værdien af ​​"@Query"-variablen. Den resulterende forespørgsel vil se sådan ud i outputtet:

SELECT * FROM

(SELECT 
	city,
	total_score
FROM 
	student
)
AS StudentTable
PIVOT(
	AVG(total_score)
	FOR city IN ([Leeds],[Liverpool],[London],[Manchester])
) AS StudentPivotTable

Det er præcis den type forespørgsel, vi ønsker at udføre. Dette er dog i String-formatet. Det sidste trin er at udføre denne SQL-forespørgsel gemt som en tekststreng. For at gøre dette bruger vi Dynamic SQL.

Udførelse af dynamisk SQL

Vi bruger den indbyggede procedure "sp_executesql" til at udføre dynamisk SQL. Vi vil bruge denne lagrede procedure til at udføre forespørgslen, der er gemt i @Query-variablen. Vores sidste forespørgsel, der opretter en dynamisk pivottabel, ser sådan ud:

USE schooldb

DECLARE @CityNames NVARCHAR(MAX) = ''
DECLARE @Query NVARCHAR(MAX) = '' 

SELECT  @CityNames +=   QUOTENAME(city)+ ','
FROM 
(
	SELECT DISTINCT city
	FROM student
) AS CITIES

SET @CityNames = LEFT(@CityNames, LEN(@CityNames)-1)

SET @Query =
'SELECT * FROM

(SELECT 
	city,
	total_score
FROM 
	student
)
AS StudentTable
PIVOT(
	AVG(total_score)
	FOR city IN (' + @CityNames +')
) AS StudentPivotTable'

EXECUTE sp_executesql @Query

Når du udfører ovenstående forespørgsel, bør du se følgende resultat:

[tabel id=37 /]

Men denne gang specificerede vi ikke manuelt værdierne for pivottabellens overskrifter. I stedet er overskrifterne blevet beregnet dynamisk, hvilket resulterer i en dynamisk pivottabel.


  1. Sådan importeres en database ved hjælp af kommandolinjen

  2. mySQL ::indsætte i tabel, data fra en anden tabel?

  3. Postgresql:Scripting af psql-udførelse med adgangskode

  4. Hvorfor bruger iteration gennem et stort Django QuerySet enorme mængder hukommelse?