itrain-home Kinderpatenschaften mit Plan Deutschland  
home
 Aktuelle Seite:  knowhow sql tsql pivot pivot.asp 
 



 

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.

 

Leerraum

Dokument zum Drucken anzeigen
English Pages
Link-Tipp zum Thema ".net Allgemein": www.codeproject.com/

Sehr umfangreiche Site zu den Themen C++, C# und dot.Net Entwicklung