Vinzenz Mai: Matrix aus Tabellen

Beitrag lesen

Hallo Stoni,

Über einen ersten Syntax wäre ich auch dankbar. Wie gesagt bin ziemlicher DB-Neuling.

und schon gleich eine Kreuztabelle, na sowas aber auch :-)
Ein kleines Tutorial, getestet mit Transact-SQL, dem SQL-Dialekt des MS SQL-Server:

Gegeben folgende Tabellen:

Tabelle "Lieferanten"
l_id        Lieferant
----------- ---------
1           Otto
2           Conrad

Tabelle "Produkte"
p_id        Produkt
----------- ----------
1           Fernseher
2           Kleid
3           Lötkolben

Tabelle "WerLiefertWas"
l_id        p_id
----------- -----------
1           1
1           2
2           1
2           3
2           3

Bitte beachte, dass in der Tabelle "WerLiefertWas" die Kombination Conrad/Lötkolben gleich zweimal auftaucht. Dies ist beabsichtigt, es bedeutet "Conrad liefert zwei unterschiedliche Lötkolben". Die restlichen Eigenschaften habe ich hier einfach weggelassen.

Wenn uns nun wirklich interessiert, welcher Lieferant welches Produkt liefert, so bekommen wir diese Informationen über den INNER JOIN

  
SELECT  
 L.Lieferant,  
 P.Produkt  
FROM  
 (Lieferanten L  
INNER JOIN WerLiefertWas W  
ON L.l_id = W.l_id)  
INNER JOIN Produkte P  
ON W.p_id = P.p_id;  

Das Ergebnis dieser Abfrage sieht wie folgt aus:

Lieferant Produkt
--------- ----------
Otto      Fernseher
Otto      Kleid
Conrad    Fernseher
Conrad    Lötkolben
Conrad    Lötkolben

Mehr zu JOINs findest Du in Fortgeschrittene Joins.

Nun zum trickreichen Teil, der Erzeugung der Kreuztabelle:

Der erste Schritt ist noch ganz einfach. Wir nutzen GROUP BY, um gleichartige Datensätze zu gruppieren:

SELECT  
    Lieferant  
FROM  
    (Lieferanten L  
INNER JOIN WerLiefertWas W  
ON L.l_id = W.l_id)  
INNER JOIN Produkte P  
ON W.p_id = P.p_id  
GROUP BY Lieferant

Dieses Ergebnis:
Lieferant
---------
Conrad
Otto

(2 Zeile(n) betroffen)

hätten wir auch einfacher bekommen können. Es ist ja nur der erste Schritt.

Nun müssen wir noch aus den einzelnen Produkten Spalten erzeugen und vor allem den richtigen Wert an die richtige Stelle schreiben. Dazu nutzen wir aus, dass der Buchstabe 'X' in der Sortierreihenfolge größer ist als der Buchstabe 'O' (ein O wie in Ohren :-)).

SELECT  
    Lieferant,  
    MAX(CASE WHEN Produkt = 'Fernseher' THEN 'X' ELSE 'O' END) AS 'Fernseher',  
    MAX(CASE WHEN Produkt = 'Kleid'     THEN 'X' ELSE 'O' END) AS 'Kleid',  
    MAX(CASE WHEN Produkt = 'Lötkolben' THEN 'X' ELSE 'O' END) AS 'Lötkolben'  
FROM  
    (Lieferanten L  
INNER JOIN WerLiefertWas W  
ON L.l_id = W.l_id)  
INNER JOIN Produkte P  
ON W.p_id = P.p_id  
GROUP BY Lieferant

liefert das gewünschte Ergebnis:
Lieferant Fernseher Kleid Lötkolben
--------- --------- ----- ---------
Conrad    X         O     X
Otto      X         X     O

(2 Zeile(n) betroffen)

Wenn ein Lieferant ein bestimmtes Produkt liefert, dann gibt es ein 'X', liefert er es mehrfach, dann gibt es entsprechend viele 'X', gibt es das Produkt nicht, dann gibt es ein 'O'. Zurückgeliefert wird das Maximum, das sobald mindestens ein 'X' da ist, d.h. sobald der Lieferant das Produkt liefert, ein 'X'. Wenn der Lieferant dieses Produkt nicht liefert, dann gibt es ein 'O'.
Du solltest leicht erkennen können, wie du diese Abfrage in Abhängigkeit vom Inhalt der Tabelle Produkte skriptgesteuert erstellen kannst.

Für jeden unterschiedlichen Eintrag in der Tabelle Produkte musst Du Deinem SQL-Statement eine Zeile der Form

[code lang=sql]MAX(CASE WHEN Produkt = 'Eintrag' THEN 'X' ELSE 'O' END) AS 'eintrag'

hinzufügen. Achte dabei auf richtige Kommasetzung. Viel Erfolg!

Freundliche Grüße

Vinzenz