|
Pivot-Tabellen mit dem SQL Server 7.0 erzeugen
In Excel ist es kein Problem Kreuztabellen-Abfragen zu erzeugen - auf dem SQL
Server kann das zu einem nicht ganz einfachen Unterfangen werden.
Falls Sie schon wissen, wie eine Pivot-Tabelle mit Hilfe
von CASE und CUBE gebildet werden, können Sie sich auch gleich anschauen, wie man solche Kreuztabellen mit einer gespeicherten Prozedur
dynamisch erzeugen kann.
Die Grundlagen
Ein einfaches Beispiel: In einer Tabelle sind die
Verkäufe für ein Produkt für jeden Verkäufer abgelegt. Es soll ein Bericht erzeugt werden, der die Verkäufe für jeden
Verkäufer und jedes Produkt anzeigt. Außerdem sollen die Gesamtsummen für Produkt und
Verkäufer angezeigt werden.
Die Ausgangstabelle könnte so aussehen:
Tabelle Verkäufe
| Produkt |
Verkäufer |
Umsatz |
| Milch |
Maier |
12 |
| Milch |
Müller |
8 |
| Honig |
Schulze |
2 |
| Milch |
Schulze |
34 |
| Butter |
Maier |
17 |
| Butter |
Müller |
2 |
| Honig |
Maier |
19 |
Das gewünschte Ergebnis sollte so aussehen:
| Produkt |
Maier |
Müller |
Schulze |
Summe |
| Butter |
17 |
2 |
0 |
19 |
| Honig |
19 |
0 |
2 |
21 |
| Milch |
12 |
8 |
34 |
54 |
| Summe |
48 |
10 |
36 |
94 |
Bleibt die einfache Frage: Wie kommt man von der Ausgangstabelle mit einer
einfachen SELECT-Anweisung zum gewünschten Ergebnis.
Ein kleiner Blick in die Online_Dokumentation hilft schnell weiter (Stichwort
Pivot oder Kreuztabelle).
Die Abfrage müsste demnach so aufgebaut sein:
SELECT Produkt, -- das ist noch
einfach -- aber jetzt müssen
CASE-Anweisungen für jeden Verkäufer geschrieben
werden:
SUM(CASE [Verkäufer] WHEN 'Maier' Then Umsatz ELSE 0 END) As 'Maier',
SUM(CASE [Verkäufer] WHEN 'Müller' Then Umsatz ELSE 0 END) As 'Müller',
SUM(CASE [Verkäufer] WHEN 'Schulze' Then Umsatz ELSE 0 END) As 'Schulze' FROM [Verkäufe]
GROUP BY Produkt
Das Ergebnis sieht so aus:
| Produkt |
Maier |
Müller |
Schulze |
| Butter |
17 |
2 |
0 |
| Honig |
19 |
0 |
2 |
| Milch |
12 |
8 |
34 |
Das sieht ja schon sehr vielversprechend aus. Fehlen eigentlich nur noch die
Summen für Spalten und Zeilen.
Also an die Arbeit: Für die Zeilensummen können wir die Abfrage
einfach mit der SUM-Aggregatfunktion erweitern:
SELECT Produkt,
SUM(CASE [Verkäufer] WHEN 'Maier' Then Umsatz ELSE 0 END) As 'Maier',
SUM(CASE [Verkäufer] WHEN 'Müller' Then Umsatz ELSE 0 END) As 'Müller',
SUM(CASE [Verkäufer] WHEN 'Schulze' Then Umsatz ELSE 0 END) As 'Schulze', -- für
jede Zeile wird eine Summenspalte hinzugefügt: SUM(Umsatz) As
Summe FROM [Verkäufe]
GROUP BY Produkt
Und schon sieht das Ergebnis schon fast wie gewünscht aus:
| Produkt |
Maier |
Müller |
Schulze |
Summe |
| Butter |
17 |
2 |
0 |
19 |
| Honig |
19 |
0 |
2 |
21 |
| Milch |
12 |
8 |
34 |
54 |
Die Online-Dokumentation liefert noch einen kurzen Hinweis auf CUBE und
ROLLUP - also ein neuer Versuch (mit CUBE)
SELECT Produkt,
SUM(CASE [Verkäufer] WHEN 'Maier' Then Umsatz ELSE 0 END) As 'Maier',
SUM(CASE [Verkäufer] WHEN 'Müller' Then Umsatz ELSE 0 END) As 'Müller',
SUM(CASE [Verkäufer] WHEN 'Schulze' Then Umsatz ELSE 0 END) As 'Schulze',
SUM(Umsatz)
As Summe FROM [Verkäufe] GROUP BY Produkt -- diesesmal mit CUBE: WITH CUBE
| Produkt |
Maier |
Müller |
Schulze |
Total |
| Butter |
17 |
2 |
0 |
19 |
| Honig |
19 |
0 |
2 |
21 |
| Milch |
12 |
8 |
34 |
54 |
| NULL |
48 |
10 |
36 |
94 |
Prima! Fast Perfekt. Fehlt nur noch eine schönere Bezeichung für die Summe
in der Spalte Produkt (letzte Zeile).
Für den Fall, dass es sich um den gruppierten Wert handelt, soll der Text
"Summe" angezeigt werden. Also wieder ab in die Transact-SQL Hilfe zum
Thema "WITH CUBE". Hier steht die Lösung, direkt zum Abschreiben:
Handelt es sich um eine gruppierte Zeile, so gibt die Funktion GROUPING 1
zurück. Das kann leicht in eine entsprechende CASE-Anweisung eingebaut
werden:
-- falls gruppiert wird, dann soll "Summe" ausgegeben werden,
ansonsten einfach der Name des Produkts: SELECT
CASE WHEN GROUPING(Produkt) =
1 THEN 'Summe' ELSE Produkt END,
-- der Rest bleibt wie gehabt:
SUM(CASE [Verkäufer] WHEN 'Maier' Then Umsatz ELSE 0 END) As 'Maier',
SUM(CASE [Verkäufer] WHEN 'Müller' Then Umsatz ELSE 0 END) As 'Müller',
SUM(CASE [Verkäufer] WHEN 'Schulze' Then Umsatz ELSE 0 END) As 'Schulze',
SUM(Umsatz)
As Summe FROM [Verkäufe] GROUP BY Produkt WITH CUBE
Et Voilà: Die Lösung - wie gewünscht!
| Produkt |
Maier |
Müller |
Schulze |
Summe |
| Butter |
17 |
2 |
0 |
19 |
| Honig |
19 |
0 |
2 |
21 |
| Milch |
12 |
8 |
34 |
54 |
| Summe |
48 |
10 |
36 |
94 |
Das Ziel ist erreicht. Aber was passiert, wenn ein neuer Verkäufer in der Ausgangstabelle hinzugefügt wird?
Seine Verkäufe würden in unserem Kreuztabellenbericht
einfach unterdrückt. Es liegt also nahe, nach einem allgemeineren Weg zu suchen,
solche Kreuztabellenberichte für beliebige Grundtabellen bzw. Abfragen zu
erzeugen. Auf den nächsten Seiten
erfahren Sie wie es geht.
|