Die Angst des Programmierers vor dem SQL-Join

Ein Artikel von Jeff Atwood in seinem Blog „Coding Horror“ sowie zwei passgenau zum gleichen Zeitpunkt sich ereignende programmiertechnische Episoden reizen mich, mal eine Lanze für Joins in SQL-Statements zu brechen. Joins sind eine schöne Sache und eigentlich nicht sehr schwierig. Aktuelle RDBMS kommen prima mit Joins aus, also gibt es Gründe, auf Joins zu verzichten?

Beginnen wir mal mit zwei Tabellen, um die Vergleiche zu beginnen. Als Thema bewege ich mich mal auf glühende Kohlen, also ab in die Politik!

[sourcecode language=“sql“]
CREATE TABLE `spd_politiker` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(40) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB; [/sourcecode]

[sourcecode language=“sql“]
CREATE TABLE `minister` (
`ID` int(11) NOT NULL,
`Name` varchar(40) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB; [/sourcecode]

….und zum Spielen nehmen wir auch noch ein paar Daten aus dem harten Berliner Politikalltag…

Tabelle Minister:                  Tabelle SPD-Politiker
ID Name                            ID Name
-- ----                            -- ----
 1 Frank-Walter Steinmeier          1 Franz Müntefering
 2 Wolfgang Schäuble                2 Frank-Walter Steinmeier
 3 Brigitte Zypries                 3 Brigitte Zypries
 4 Peer Steinbrück                  4 Peer Steinbrück
 5 Michael Glos                     5 Ulla Schmidt
 6 Franz Müntefering                6 Wolfgang Tiefensee
 7 Horst Seehofer                   7 Sigmar Gabriel
 8 Franz Josef Jung                 8 Willy Brandt
 9 Ursula von der Leyen             9 Helmut Schmidt
10 Ulla Schmidt                    10 Gerhard Schröder
11 Wolfgang Tiefensee              11 Kurt Beck
12 Sigmar Gabriel                  12 Johannes Rau
13 Annette Schavan

Ran an die SQL-Joins…

1. INNER JOIN

Inner JoinEin inner join liefert im Prinzip die Schnittmenge aus beiden Grundmengen. Für das konstruierte Beispiel aus der Politik würden also alle Minister ausgegeben werden, welche gleichzeitig SPD-Politiker sind bzw. waren.

[sourcecode language=“sql“]
select * from minister
inner join spd_politiker on minister.Name = spd_politiker.Name;
[/sourcecode]

ID Name ID Name
1 Frank-Walter Steinmeier 2 Frank-Walter Steinmeier
3 Brigitte Zypries 3 Brigitte Zypries
4 Peer Steinbrück 4 Peer Steinbrück
6 Franz Müntefering 1 Franz Müntefering
10 Ulla Schmidt 5 Ulla Schmidt
11 Wolfgang Tiefensee 6 Wolfgang Tiefensee
12 Sigmar Gabriel 7 Sigmar Gabriel

In diesem Fall kann man das gewünschte Ergebnis noch etwas einfacher erhalten, jedoch behandelt dieser Artikel das Verhalten von Joins…!

2. LEFT (OUTER) JOIN

Left JoinEin left outer join liefert als Ergebnis alle Datensätze der ersten Tabelle sowie alle passenden Datensätze von Tabelle 2. Hier werden somit alle Minister ausgegeben, als Ergänzung erscheinen die Daten aus der SPD-Politiker-Tabelle, falls ein Minister dort enthalten sein sollte.

[sourcecode language=“sql“]
select * from minister
left outer join spd_politiker
on minister.Name = spd_politiker.Name;
[/sourcecode]

ID Name ID Name
1 Frank-Walter Steinmeier 2 Frank-Walter Steinmeier
2 Wolfgang Schäuble (NULL) (NULL)
3 Brigitte Zypries 3 Brigitte Zypries
4 Peer Steinbrück 4 Peer Steinbrück
5 Michael Glos (NULL) (NULL)
6 Franz Müntefering 1 Franz Müntefering
7 Horst Seehofer (NULL) (NULL)
8 Franz Josef Jung (NULL) (NULL)
9 Ursula von der Leyen (NULL) (NULL)
10 Ulla Schmidt 5 Ulla Schmidt
11 Wolfgang Tiefensee 6 Wolfgang Tiefensee
12 Sigmar Gabriel 7 Sigmar Gabriel
13 Annette Schavan (NULL) (NULL)

Häufig verwende ich diese left outer joins, um Datensätze zu finden, welche nicht in der anderen Tabelle vorhanden sind. Hierfür kann man die SQL-Abfrage leicht modifizieren – das Ergebnis ist in diesem Falle alle Nicht-SPD-Minister:

[sourcecode language=“sql“]
select * from minister
left outer join spd_politiker
on minister.Name = spd_politiker.Name
where spd_politiker.ID IS NULL;
[/sourcecode]

3. RIGHT (OUTER) JOIN

Ein right outer join funktioniert eigentlich genauso wie ein left outer join liefert als Ergebnis alle Datensätze der zweiten Tabelle sowie alle passenden Datensätze von Tabelle 1. Hier werden somit alle SPD-Politiker ausgegeben, als Ergänzung erscheinen die Daten aus der Minister-Tabelle, falls der Politiker dort auch ein Amt bekleidet.

[sourcecode language=“sql“]
select * from minister
right outer join spd_politiker
on minister.Name = spd_politiker.Name;
[/sourcecode]

ID Name ID Name
6 Franz Müntefering 1 Franz Müntefering
1 Frank-Walter Steinmeier 2 Frank-Walter Steinmeier
3 Brigitte Zypries 3 Brigitte Zypries
4 Peer Steinbrück 4 Peer Steinbrück
10 Ulla Schmidt 5 Ulla Schmidt
11 Wolfgang Tiefensee 6 Wolfgang Tiefensee
12 Sigmar Gabriel 7 Sigmar Gabriel
(NULL) (NULL) 8 Willy Brandt
(NULL) (NULL) 9 Helmut Schmidt
(NULL) (NULL) 10 Gerhard Schröder
(NULL) (NULL) 11 Kurt Beck
(NULL) (NULL) 12 Johannes Rau

Auch mit dem right outer joins kann man wunderbar die IS NULL-Eigenschaft verwenden, um Datensätze zu finden, welche nicht in der anderen Tabelle vorhanden sind.

4. FULL OUTER JOIN
Full Outer JoinEin full outer join gibt eigentlich alle Datensätze von Tabelle A und Tabelle B aus, wobei die Schnittmenge zusammengefasst wird. Ein paar RDBMS, wie z.B. auch MySQL, haben keine direkte Unterstützung des full outer join, jedoch kann man ohne viel Umstand SQL-Konstrukte basteln, die dies imitieren – schließlich ist das ja nichts anderes wie eine Zusammenfassung des left outer join und des right outer join.

Hier ein Beispiel eines Workarounds für MySQL mit Verwendung von union all:
[sourcecode language=“sql“]
select * from minister
left outer join spd_politiker
on minister.Name = spd_politiker.Name
union all
select * from minister
right outer join spd_politiker
on minister.Name = spd_politiker.Name
where minister.Name is null;
[/sourcecode]

ID Name ID Name
1 Frank-Walter Steinmeier 2 Frank-Walter Steinmeier
2 Wolfgang Schäuble (NULL) (NULL)
3 Brigitte Zypries 3 Brigitte Zypries
4 Peer Steinbrück 4 Peer Steinbrück
5 Michael Glos (NULL) (NULL)
6 Franz Müntefering 1 Franz Müntefering
7 Horst Seehofer (NULL) (NULL)
8 Franz Josef Jung (NULL) (NULL)
9 Ursula von der Leyen (NULL) (NULL)
10 Ulla Schmidt 5 Ulla Schmidt
11 Wolfgang Tiefensee 6 Wolfgang Tiefensee
12 Sigmar Gabriel 7 Sigmar Gabriel
13 Annette Schavan (NULL) (NULL)
(NULL) (NULL) 8 Willy Brandt
(NULL) (NULL) 9 Helmut Schmidt
(NULL) (NULL) 10 Gerhard Schröder
(NULL) (NULL) 11 Kurt Beck
(NULL) (NULL) 12 Johannes Rau

Mehr Methoden, um einen full outer join mit MySQL nachzubauen, habe ich hier gefunden.

Anmerkung:
Wie der Kommentator Steffen korrekterweise moniert, ist ein JOIN tatsächlich keine Schnittmenge, sondern vielmehr ein kartesisches Produkt in Verbindung mit einer Selektion. Datenbanktheoretiker mögen mich strafen, aber ich bleibe dennoch bei meiner starken Vereinfachung in diesem Artikel!


Beitrag veröffentlicht

in

, ,

von

Schlagwörter:

Kommentare

27 Antworten zu „Die Angst des Programmierers vor dem SQL-Join“

  1. Avatar von Walter
    Walter

    KLASSE BEISPIELE!!! Ich habe es durch Deine plastischen Beipiele endlich kapiert 🙂

  2. Avatar von Stefan Ganz

    Vielen Dank,
    habe nach einem SQL-Statement gesucht, dass mir nicht die Schnittmenge liefert und das hat mit left outer join prima funktioniert.
    Beste Grüße

  3. Avatar von Björn

    Hallo Steffen,

    das ist natürlich fachlich vollkommen korrekt, und um den querulatorischen Frieden zu wahren ist nun eine kleine Fußnote in dem Artikel.

    Beste Grüße,
    Björn

  4. Avatar von Steffen
    Steffen

    Hallo Björn,
    die Relationale Algebra definiert das o.g. sauber und hinreichend verständlich (kartesisches Produkt&Selektion). Es gibt Aussagen, die man „unter Brüdern“ gelten lassen könnte: um im Bsp. zu bleiben „Politiker sind **********“. Der Aussage „Inner Joins = Schnittmenge“ kann man auch „unter Brüdern“ nicht zustimmen.

    Querulatorischen aber lieben Gruß
    Steffen

  5. Avatar von Björn

    Hallo Steffen,

    klar kann – je nach Anwendungsfall der INNER JOIN mehr Datensätze produzieren als in den Quelltabellen. Ziel der Visualisierung ist jedoch auf Basis von möglichst einfach verständlichen Daten es fürs Auge zu transportieren.

    Gegenfrage:
    Wie würdest Du es möglichst einfach beschreiben?

    Viele Grüße,
    Björn

  6. Avatar von Steffen
    Steffen

    Hallo Björn,
    mir geht es nicht um didaktische Aspekte, sondern um die Tatsache, dass eine via Inner Join generierte Tabelle bspw. mehr Datensätze enthalten kann, als die abgefragten Tabellen zusammen. Mich wundert, dass dieser Umstand hier niemanden und insbesondere Dich nicht stört?!
    Also schon quantitativ ist die Aussage „Inner Join = Schnittmenge“ einfach nur FALSCH! Da hilft es gar nicht, dass es doch so schön anschaulich ist…
    Auch die Aussage „Politiker sind häßliche Frauen mit schrecklichen Dekolletes“ mag leicht verständlich sein und sogar auf unsern süßen Kanzlerengel zutreffen, aber i.A. bleibt es eben falsch!

    Liebe Grüße
    Steffen

  7. Avatar von Björn

    Ein Mengendiagramm ist sicherlich nicht wissenschaftlich die beste Visualisierung eines Joins, aber es hat den Vorteil, dass es fast jeder kennt. Ich halte es auch nach mehreren Jahren für eine gute Näherung.

  8. Avatar von Steffen
    Steffen

    Hallo,
    die Visualisierung mittels Venn-Diagrammen ist hier, wie auch an vielen anderen Stellen im I-Net falsch. Bspw. kann die Schnittmenge zweier Tabellen i.A. nicht über ein
    einfaches Inner Join gebildet werden.
    Gruß
    Steffen

  9. Avatar von Kristian

    Sehr gut veranschaulicht und sehr hilfreich. Vielen Dank!
    Daran könnte sich der Eine oder Andere Lehrkörper ein Beispiel nehmen 🙂

  10. Avatar von Fuci2022
    Fuci2022

    Wirklich klasse!!! Einfach und effektiv erklärt ! Solche Beiträge erleichtern das Leben 🙂

  11. Avatar von Rüdiger
    Rüdiger

    Bravo,
    endlich habe ich es kapiert… Klasse Anleitung, Respekt

  12. Avatar von Lars

    Eine durchaus gelungene Anleitung:). Ich verstehe auch nicht, warum sich viele vor der join-Thematik scheuen. Erleichtert den SQL-Alltag schließlich ungemein.
    Mein Favorit (zwar auf Englisch, aber dennoch sehr schön geschildert und verbildlicht):
    http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins

    Beste Grüße,
    Lars

  13. Avatar von Björn

    In meinen Beispielen geht es eher darum, die Relationen darzustellen, welche sich aus den diversen JOIN-Varianten ergeben. Durch die eindeutigen Namen gibt es nur 1:1-Relation. Das von Ihnen beschriebene Szenario kommt vor, wenn man mit 1:n-Relationen arbeitet. Hier hilft DISTINCT (falls man es denn möchte), denn diese Option legt fest, dass doppelte Datensätze aus der Ergebnismenge entfernt werden.

  14. Avatar von Carsten Guddat
    Carsten Guddat

    Hallo, ich dachte auch, dass ich das Wesentliche Begriffen habe, bis ich auf folgendes Problem stieß: wenn in der Tabelle B ein Eintrag doppelt vorkommt, wird er beim dieser passgleiche Eintrag doppelt angezeigt. Vermutlich muss man dann noch den Select mit einem Distinct ausführen um das Problem zu beheben. Richtig?

  15. Avatar von Björn

    Danke! Eigentlich wollte ich auch den Artikel um den NATURAL JOIN erweitern, jedoch fand ich bislang kein passendes Beispiel. Vielmehr wäre es sicher irgendwann einmal sinnvoll, den Artikel auf die aktuellen politischen Gegebenheiten zu aktualisieren – da warte ich aber erstmal die Wahlen im Herbst ab!

  16. Avatar von Stephan
    Stephan

    Ich kann mich meinen Vorrednern nur anschließen. Sehr gute Seite. Fast schon vorbildlich 😉

    Eventuell könnte man die Übersicht noch um die Natural joins erweitern

  17. Avatar von Christoph Koenig

    Die Abfrage aller Nicht-SPD-Minister würde ich ja eher so machen (hat dann aber nichts mit Joins zu tun):

    select * from minister
    where id not in
    (
    select id
    from spd_politiker
    )

  18. Avatar von Denise
    Denise

    Eine sehr hilfreiche Seite, weil es wirklich einfach und verständlich erklärt ist!

  19. Avatar von Watte
    Watte

    Sehr, sehr hilfreich! Habs nun endlich mal verstanden, und hoffe es hilft mir auch über die mündliche Informatik-Abiturprüfung hinaus 😉 Viele Dank!

  20. […] Angst des Papstes vor dem Volk«, »Die Angst des Erfolgreichen vor dem Fall«, »Die Angst des Programmierers vor dem SQL-Join«, »Die Angst des Pfarrers vor dem Glaubensbekenntnis«, »Die Angst der Giraffe vor […]

  21. Avatar von Stefano

    Supeeer !!! Weiter so…!!

  22. Avatar von Thorsten
    Thorsten

    Prima erklärt mit einem lebensnahen und einfach nachvollziehbaren Beispiel. Klasse!

  23. Avatar von Ama
    Ama

    Sehr aufschlussreich geschrieben.
    Jetzt kann meine Klausur kommen 😉
    Großes Lob

  24. Avatar von BOBmoraine
    BOBmoraine

    Vielen Dank, super aufgearbeitet, hat mir sehr geholfen

  25. Avatar von Björn

    Gern geschehen! 🙂 Vielleicht sollte ich irgendwann einmal die benannten Politiker in diesem Tutorial aktualisieren…

  26. Avatar von Hannes Umbreit
    Hannes Umbreit

    Vielen Dank, hat mir sehr geholfen!

  27. Avatar von tres_chef

    Jo, sehr gut die verschiedenen joins erklärt. Ich fand die Seite http://www.sqlexikon.de auch ganz hilfreich, gut v.A. für SQL-Anfänger.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.