Hallo Martin,
ich habe 5 Tabellen (für jedes Jahr eine) mit der gleichen Struktur (ID,Name,...).
Damals hielt sich mein Wissen über eine gute Tabellenstruktur noch stark in Grenzen.
es wäre eine sehr gute Idee, Deine Tabellenstruktur zu bereinigen.
Ich möchte jetzt eine neue Tabelle machen damit ich weiß welches Mitglied im welchen Jahr welche ID hat.
Name | ID 2002 | ID 2003 | ID 2004
z.B. Mayer| 1 | 4 | NULL
Das Problem dabei ist das es Mitglieder gibt die für alle 5 Jahre (also in jeder Tabelle) einen Eintrag haben.
Aber auch welche die nur in den ersten 2 Jahren dabei waren bzw. erst letztes Jahr dazu gekommen sind.
Die ID kann dabei in jedem Jahr unterschiedlich sein.
Dazu hab ich in den letzten Tagen viel mit join-Abfragen herumexperimentiert aber es zu keinem zufriedenstellenden Ergebnis gebracht.
Hier empfehle ich Dir fogende Artikel:
Einführung Joins
Fortgeschrittene Joins
Ist so eine Abfrage mit join überhaupts möglich?
Das hängt von Deinem Datenbankmanagementsystem (DBMS) ab.
Im folgenden möchte ich Dir eine unter MS SQL-Server (2000 und neuer) funktionierende Lösung vorstellen:
Ausgangstabellen:
Tabelle pv01
ID name
----------- ------------
1 Martin
2 Jens
3 Marc
Tabelle pv02
ID name
----------- ------------
1 Marc
2 Martin
3 Vinzenz
Tabelle pv03
ID name
----------- ------------
1 Vinzenz
2 Martin
3 Rouven
gewünschtes Ergebnis:
name ID 2001 ID 2002 ID 2003
------------ ----------- ----------- -----------
Martin 1 2 2
Jens 2 NULL NULL
Marc 3 1 NULL
Vinzenz NULL 3 1
Rouven NULL NULL 3
Um zum gewünschten Ergebnis zu gelangen verwende ich den FULL OUTER JOIN. Dieser wird nicht von jedem DBMS unterstützt, so z.B. von MySQL. Weiterhin gehe ich in meinem Beispiel davon aus, dass sich jedes Mitglied (unwahrscheinlicherweise) über seinen Namen eindeutig identifizieren läßt, d.h. als JOIN-Spalte verwende ich die Spalte "name".
1. Schritt: Ermittle die IDs der Jahre 2001 und 2002
SELECT
pv01.name,
pv02.name,
pv01.ID AS [ID 2001],
pv02.ID AS [ID 2002]
FROM pv01
FULL OUTER JOIN pv02
ON pv01.name = pv02.name
Resultat:
name name ID 2001 ID 2002
------------ ------------ ----------- -----------
Martin Martin 1 2
Jens NULL 2 NULL
Marc Marc 3 1
NULL Vinzenz NULL 3
Wie Du siehst, werden sowohl die Datensätze von Tabelle pv01 angezeigt, die keine Entsprechung in Tabelle pv02 haben, als auch die Datensätze von Tabelle pv02, die keine Entsprechung in Tabelle pv01 haben.
2. Schritt: Erzeuge die Spalte mit allen Namen.
Hier hilft die Funktion COALESCE(arg1, arg2, ...), die das erste von NULL verschiedene Argument zurückliefert.
SELECT
COALESCE(pv01.name, pv02.name) AS 'Mitglied',
pv01.name,
pv02.name,
pv01.ID AS [ID 2001],
pv02.ID AS [ID 2002]
FROM pv01
FULL OUTER JOIN pv02
ON pv01.name = pv02.name
Resultat:
Mitglied name name ID 2001 ID 2002
------------ ------------ ------------ ----------- -----------
Martin Martin Martin 1 2
Jens Jens NULL 2 NULL
Marc Marc Marc 3 1
Vinzenz NULL Vinzenz NULL 3
3. Schritt: Tabelle pv03 mit hinzunehmen, wieder mit FULL OUTER JOIN
Wir joinen das Ergebnis der ersten Join-Operation (pv01 FULL OUTER JOIN pv02) mit der Tabelle pv03. Wiederum erfolgt die Join-Operation über die Spalte pv03.name. Als Partner kann weder pv01.name noch pv02.name dienen, da beide NULL-Werte enthalten (können). Aus diesem Dilemma hilft wieder die COALESCE-Funktion. Weiter habe ich die Namensspalten der Jahrestabellen aus dem Statement entfernt.
SELECT
COALESCE(pv01.name, pv02.name, pv03.name) AS 'name',
pv01.ID AS [ID 2001],
pv02.ID AS [ID 2002],
pv03.ID AS [ID 2003]
FROM (pv01
FULL OUTER JOIN pv02
ON pv01.name = pv02.name)
FULL OUTER JOIN pv03
ON COALESCE(pv01.name, pv02.name) = pv03.name
liefert das gewünschte Resultat:
name ID 2001 ID 2002 ID 2003
------------ ----------- ----------- -----------
Martin 1 2 2
Jens 2 NULL NULL
Marc 3 1 NULL
Vinzenz NULL 3 1
Rouven NULL NULL 3
(5 Zeile(n) betroffen)
Auf analoge Weise kann man das Statement auf fünf Tabellen erweitern.
Es gibt sicherlich auch andere Lösungsmöglichkeiten. Ob es für Dein DBMS eine Lösung gibt, die aus einem einzigen SQL-Statement besteht, kann ich Dir natürlich nicht sagen. Obige Lösung wurde mit der MS SQL Server 2005 Express Edition getestet.
Freundliche Grüße
Vinzenz
PS: Mit einem Kreuzprodukt hat Deine Tabelle nichts zu tun, sie erinnert an eine Kreuztabelle (auch Pivot-Tabelle genannt). Außer Jet-SQL, dem SQL-Dialekt der Jet-Engine (das DBMS hinter MS Access), kenne ich kein SQL-Dialekt, der Kreuztabellenabfragen direkt unterstützt.