Database
 sql >> Datenbank >  >> RDS >> Database

Erstellen einer dynamischen Pivot-Tabelle mit der QUOTENAME-Funktion

In meinem vorherigen Artikel über den grundlegenden Pivot-Operator haben wir gesehen, wie der Pivot-Operator verwendet werden kann, um Zeilen in Spalten umzuwandeln, was zu Pivot-Tabellen führt. Wir haben gesehen, dass es drei Hauptschritte gibt, um eine Pivot-Tabelle zu erstellen. Der erste Schritt war die Auswahl der Basisdaten. Der zweite Schritt bestand darin, die Basisdaten in einen Tabellenausdruck umzuwandeln, und im letzten Schritt wurde ein Pivot-Operator auf die temporären Daten angewendet, wodurch die Pivot-Tabelle entstand.

Sehen Sie sich das Beispiel unten an.

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

Hinweis: Informationen zum Erstellen der Dummy-Datenbank und -Daten finden Sie im vorherigen Artikel zum Pivot-Operator.

Einschränkungen des Pivot-Operators

Es gibt jedoch bestimmte Einschränkungen des Pivot-Operators. Innerhalb des Pivot-Operators müssen wir das aggregierte Feld und die Spalten angeben, für die wir unsere Daten pivotieren möchten. Abschließend müssen wir noch die individuellen Werte für die zu erstellenden Spaltenüberschriften festlegen.

Wenn wir das Skript aus dem vorherigen Abschnitt ausführen würden, würden wir das folgende Ergebnis erhalten:

[Tabellen-ID=35 /]

Die Überschriften der Spalten sind die einzelnen Werte innerhalb der Stadtspalte. Wir haben diese Werte innerhalb des Pivot-Operators in unserer Abfrage angegeben.

Der mühsamste Teil beim Erstellen von Pivot-Tabellen ist das manuelle Festlegen der Werte für die Spaltenüberschriften. Dies ist der fehleranfälligste Teil, insbesondere wenn sich die Daten in Ihrer Online-Datenquelle ändern. Wir können nicht sicher sein, dass die Werte, die wir im Pivot-Operator angegeben haben, in der Datenbank verbleiben, bis wir diese Pivot-Tabelle das nächste Mal erstellen.

In unserem Skript haben wir beispielsweise London, Liverpool, Leeds und Manchester als Werte für Überschriften unserer Pivot-Tabelle angegeben. Diese Werte existierten in der Spalte „Stadt“ der Schülertabelle. Was passiert, wenn einer oder mehrere dieser Werte gelöscht oder aktualisiert werden? In solchen Fällen wird null zurückgegeben.

Ein besserer Ansatz wäre, eine dynamische Abfrage zu erstellen, die einen vollständigen Satz von Werten aus der Spalte zurückgibt, aus der Sie versuchen, Ihre Pivot-Tabelle zu generieren.

Erstellen einer dynamischen Pivot-Tabelle

In diesem Abschnitt werden wir sehen, wie man eine dynamische Pivot-Tabelle erstellt.

Das bedeutet, dass wir die Werte für die Spalte, aus der wir versuchen, unsere Pivot-Tabelle zu generieren, nicht manuell angeben müssen. Stattdessen werden wir diese Werte dynamisch festlegen. Zu diesem Zweck verwenden wir die „QUOTENAME“-Funktion.

Stellen Sie wie immer sicher, dass Sie gut gesichert sind, bevor Sie mit einem neuen Code experimentieren. Lesen Sie diesen Artikel zum Sichern von MS SQL-Datenbanken, wenn Sie sich nicht sicher sind.

QUOTENAME-Funktion

Die Funktion „QUOTENAME“ formatiert ausgewählte Ergebnisse. Bevor Sie das dynamische Pivot erklären, sollten Sie sich ein schnelles Arbeitsbeispiel der Funktion „QUOTENAME“ ansehen.

Sehen Sie sich die folgende Abfrage an.

USE schooldb

SELECT QUOTENAME(city)+ ','
FROM student

Standardmäßig umschließt die „QUOTENAME“-Funktion die ausgewählten Elemente mit eckigen Klammern. Die Ausgabe der obigen Abfrage sieht folgendermaßen aus:

[Tabellen-ID=36 /]

Spaltennamen in einer Variablen speichern

Obwohl wir die Spaltenwerte in eckige Klammern eingeschlossen haben, müssen wir die Werte im Pivot-Operator in diesem Format angeben:

„[Leeds], [Liverpool], [London], [Manchester]“

Dazu benötigen wir eine Variable.

USE schooldb

DECLARE @CityNames NVARCHAR(MAX) = ''

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

PRINT @CityNames

In der obigen Abfrage haben wir eine Variable „@CityNames“ deklariert und mit einer leeren Zeichenfolge initialisiert. Dann haben wir eine SELECT-Anweisung verwendet, um verschiedene Städtenamen aus der Städtespalte auszuwählen und sie iterativ in der Variablen „@CityNames“ zu speichern. Bei jeder Iteration wird der Variablen „@CityNames“ ein eindeutiger Wert in der Stadtspalte zusammen mit einem Komma hinzugefügt.

Dann haben wir den in dieser Variablen gespeicherten Wert gedruckt. Das Ergebnis der obigen Abfrage sieht folgendermaßen aus:

„[Leeds], [Liverpool], [London], [Manchester]“,

Wenn Sie sich die Ausgabe ansehen, steht hinter dem letzten Wert ein Komma. Das brauchen wir nicht.

Entfernen eines nachgestellten Kommas

Um ein nachgestelltes Komma zu entfernen, verwenden wir eine LEFT-Funktion, die als erstes Argument einen String verwendet. Das zweite Argument ist die Anzahl der Zeichen, die von dieser Zeichenfolge ab dem ersten Zeichen zurückgegeben werden sollen. Sehen Sie sich die folgende Abfrage an:

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

Achten Sie hier auf diese Zeile des Skripts:

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

In dieser Zeile des Skripts haben wir die LEFT-Funktion verwendet, um alle Zeichen auf der linken Seite des in der Variablen „@CityNames“ gespeicherten Werts abzurufen, beginnend mit dem ersten Element. Im zweiten Argument haben wir die LEN-Funktion verwendet, um die Anzahl der Wertelemente zu berechnen, die in der Funktion „@CityNames“ gespeichert sind, und schließlich haben wir 1 davon subtrahiert. Dadurch wird das abschließende Komma aus der Zeichenfolge entfernt. Die Ausgabe sieht folgendermaßen aus:

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

Konvertieren einer SQL-Abfrage in einen String

Jetzt können wir hoffentlich die Variable „@CityNames“ in unserem Pivot-Operator wie folgt verwenden:

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

Wir können jedoch keine Variable innerhalb unseres Pivot-Operators verwenden. Der alternative Ansatz besteht darin, unsere vollständige SQL-Abfrage in einen String umzuwandeln. Innerhalb dieser Zeichenfolge werden wir unsere „@CityNames“-Variable einhaken.

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

Hier haben wir eine Variable „@Query“ deklariert und unsere SQL-Abfrage in dieser Variable gespeichert. Innerhalb des Pivot-Operators haben wir den in der Variablen „@CityNames“ gespeicherten Wert verkettet. Um zu sehen, wie die ausgeführte Abfrage aussieht, haben wir den Wert der Variablen „@Query“ gedruckt. Die resultierende Abfrage sieht in der Ausgabe so aus:

SELECT * FROM

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

Dies ist genau der Typ der Abfrage, die wir ausführen möchten. Dies ist jedoch im String-Format. Der letzte Schritt besteht darin, diese als Textzeichenfolge gespeicherte SQL-Abfrage auszuführen. Dazu verwenden wir Dynamic SQL.

Dynamisches SQL ausführen

Wir verwenden die eingebaute Prozedur „sp_executesql“, um dynamisches SQL auszuführen. Wir verwenden diese gespeicherte Prozedur, um die in der @Query-Variable gespeicherte Abfrage auszuführen. Unsere letzte Abfrage, die eine dynamische Pivot-Tabelle erstellt, sieht folgendermaßen aus:

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

Wenn Sie die obige Abfrage ausführen, sollten Sie das folgende Ergebnis sehen:

[Tabellen-ID=37 /]

Allerdings haben wir diesmal die Werte für die Überschriften der Pivot-Tabelle nicht manuell angegeben. Stattdessen wurden die Überschriften dynamisch berechnet, was zu einer dynamischen Pivot-Tabelle führte.