SQL-JOIN – Abfragen über mehrere Datentabellen
Das Prinzip des SQL-JOINs basiert auf der gleichnamigen Operation der relationalen Algebra – einer Kombination aus kartesischem Produkt und Selektion. Welche Daten der Ausgangstabellen in die Ergebnis-Tabelle übernommen werden, bestimmt der Anwender durch die Wahl eines JOIN-Typs und durch die Definition einer Selektionsbedingung.
Wir führen Sie in die mathematischen Grundlagen von SQL-JOINs ein, stellen verschiedene JOIN-Typen gegenüber und zeigen Ihnen anhand von Praxisbeispielen, wie Sie JOINs im Rahmen von Datenbankabfragen via SQL umsetzen.
Wie funktionieren SQL-JOINs?
- Kartesisches Produkt
- Selektion
Das kartesische Produkt
Als Operator für das kartesische Produkt kommt in der relationalen Algebra das Multiplikationszeichen (×) zum Einsatz.
Dazu ein Beispiel:
Das kartesische Produkt A × B der beiden Mengen A = {x, y, z} und B = {1, 2, 3} ist:
A × B = {(x,1), (x,2), (x,3), (y,1), (y,2), (y,3), (z,1), (z,2), (z,3)}
Veranschaulichen lässt sich die Rechnung anhand folgender Grafik:
A × B = {(x,1), (x,2), (x,3), (y,1), (y,2), (y,3), (z,1), (z,2), (z,3)}
B × A = {(1,x), (1,y), (1,z), (2,x), (2,y), (2,z), (3,x), (3,y), (3,z)}
In der SQL-Terminologie wird eine Operation, bei der das kartesische Produkt aus zwei Datenbanktabellen gebildet wird, als CROSS JOIN bezeichnet. In der Praxis kommen CROSS JOINs aufgrund der ungefilterten Ergebnismenge nur selten zum Einsatz.
Die Selektion
σF (R)
Der Platzhalter „F“ entspricht dem Vergleichsausdruck, einer Formel aus logischen Prädikaten, die die Selektionsbedingung definieren. R steht für den zu selektierenden Datenbestand. Alternativ bietet sich die lineare Schreibweise R[F] an.
Zum Formulieren von Selektionsbedingungen stehen die üblichen Vergleichsoperatoren zur Verfügung: beispielsweise gleich (=), größer (>) oder kleiner (<).
Wir erläutern die Selektion anhand eines Beispiels, das wir bereits im Grundlagentext zum relationalen Datenbankmodell eingeführt haben. Folgende Tabelle zeigt fiktive Personaldaten, die ein Unternehmen zu seinen Mitarbeitern erfasst haben könnte. Für jeden Mitarbeiter sind die Personalnummer (m_id), Angaben zum Namen (nachname, vorname), zur Sozialversicherungsnummer (svn), zur Adresse (str, plz, ort) sowie zum zugewiesenen Firmenwagen (kfz_id) angegeben.
Tabelle: mitarbeiter | ||||||||
---|---|---|---|---|---|---|---|---|
m_id | nachname | vorname | svn | str | nr | plz | ort | kfz_id |
1 | Schmidt | Udo | 25 120512 S 477 | Hauptstraße | 1 | 11111 | Musterhausen | 3 |
2 | Müller | Wolfgang | 25 100615 M 694 | Bahnhofstraße | 2 | 22222 | Musterheim | 1 |
3 | Meyer | Günther | 25 091225 M 463 | Am Marktplatz | 3 | 33333 | Musterfelde | 1 |
4 | Krause | Helmut | 25 170839 K 783 | Waldweg | 4 | 44444 | Musterwalde | 2 |
σkfz_id=1(mitarbeiter)
Wir rufen lediglich die Tupel ab, bei denen der Wert in der Spalte kfz_id gleich 1 ist.
Das Ergebnis entspricht folgender Tabelle.
Tabelle: mitarbeiter (selektiert) | ||||||||
---|---|---|---|---|---|---|---|---|
m_id | nachname | vorname | svn | str | nr | plz | ort | kfz_id |
2 | Müller | Wolfgang | 25 100615 M 694 | Bahnhofstraße | 2 | 22222 | Musterheim | 1 |
3 | Meyer | Günther | 25 091225 M 463 | Am Marktplatz | 3 | 33333 | Musterfelde | 1 |
SELECT * FROM mitarbeiter WHERE mitarbeiter.kfz_id = 1;
Kombination aus kartesischem Produkt und Selektion
Beide Tabellen sind über eine Fremdschlüsselbeziehung mit einander verknüpft. Der Primärschlüssel der Tabelle „kfz“ (die kfz_id) fungiert in der Tabelle „mitarbeiter“ als Fremdschlüssel.
Tabelle: mitarbeiter | |||
---|---|---|---|
m_id | nachname | vorname | kfz_id |
1 | Schmidt | Udo | 3 |
2 | Müller | Wolfgang | 1 |
3 | Meyer | Günther | 1 |
4 | Krause | Helmut | 2 |
Tabelle: kfz | |||||
---|---|---|---|---|---|
kfz_id | marke | modell | kennzeichen | baujahr | hu |
1 | VW | Caddy | B KH 778 | 2016 | 18.12.2018 |
2 | Opel | Astra | B PO 654 | 2010 | 12.08.2019 |
3 | BMW | X6 | B MW 780 | 2017 | 01.09.2018 |
σkfz_id=kfz_id(mitarbeiter × kfz)
Dabei wird zunächst das kartesische Produkt mitarbeiter × kfz gebildet. Das (Zwischen-)Ergebnis ist ein CROSS JOIN – eine Ergebnistabelle, in der jeder Tupel der Tabelle „mitarbeiter“ mit jedem Tupel der Tabelle „kfz“ kombiniert wird.
Tabelle: Kartesisches Produkt „mitarbeiter“ × „kfz“ | |||||||||
---|---|---|---|---|---|---|---|---|---|
m_id | nachname | vorname | mitarbeiter.kfz_id | kfz.kfz_id | marke | modell | kennzeichen | baujahr | hu |
1 | Schmidt | Udo | 3 | 1 | VW | Caddy | B KH 778 | 2016 | 18.12.2018 |
1 | Schmidt | Udo | 3 | 2 | Opel | Astra | B PO 654 | 2010 | 12.08.2019 |
1 | Schmidt | Udo | 3 | 3 | BMW | X6 | B MW 780 | 2017 | 01.09.2018 |
2 | Müller | Wolfgang | 1 | 1 | VW | Caddy | B KH 778 | 2016 | 18.12.2018 |
2 | Müller | Wolfgang | 1 | 2 | Opel | Astra | B PO 654 | 2010 | 12.08.2019 |
2 | Müller | Wolfgang | 1 | 3 | BMW | X6 | B MW 780 | 2017 | 01.09.2018 |
3 | Meyer | Günther | 1 | 1 | VW | Caddy | B KH 778 | 2016 | 18.12.2018 |
3 | Meyer | Günther | 1 | 2 | Opel | Astra | B PO 654 | 2010 | 12.08.2019 |
3 | Meyer | Günther | 1 | 3 | BMW | X6 | B MW 780 | 2017 | 01.09.2018 |
4 | Krause | Helmut | 2 | 1 | VW | Caddy | B KH 778 | 2016 | 18.12.2018 |
4 | Krause | Helmut | 2 | 2 | Opel | Astra | B PO 654 | 2010 | 12.08.2019 |
4 | Krause | Helmut | 2 | 3 | BMW | X6 | B MW 780 | 2017 | 01.09.2018 |
Als (End-)Ergebnis erhalten wir eine Tabelle, die beide Ausgangstabellen ohne Redundanzen zusammenführt.
Tabelle: JOIN über „mitarbeiter“ und „kfz“ | |||||||||
---|---|---|---|---|---|---|---|---|---|
m_id | nachname | vorname | mitarbeiter.kfz_id | kfz.kfz_id | marke | modell | kennzeichen | baujahr | hu |
1 | Schmidt | Udo | 3 | 3 | BMW | X6 | B MW 780 | 2017 | 01.09.2018 |
2 | Müller | Wolfgang | 1 | 1 | VW | Caddy | B KH 778 | 2016 | 18.12.2018 |
3 | Meyer | Günther | 1 | 1 | VW | Caddy | B KH 778 | 2016 | 18.12.2018 |
4 | Krause | Helmut | 2 | 2 | Opel | Astra | B PO 654 | 2010 | 12.08.2019 |
Es gilt somit:
σkfz_id=kfz_id(mitarbeiter × kfz) := mitarbeiter⋈kfz_id=kfz_idkfz
Die Operation σkfz_id=kfz_id(mitarbeiter × kfz) entspricht einem JOIN über die Tabellen „mitarbeiter“ und „kfz“ mit der Voraussetzung kfz_id=kfz_id.
Übertragen auf die SQL-Syntax entspräche die oben dargestellte Operation folgendem Statement:
SELECT * FROM mitarbeiter INNER JOIN kfz ON mitarbeiter.kfz_id = kfz.kfz_id;
SQL-JOIN-Typen
Zu den wichtigsten JOIN-Typen gehören folgende:
- INNER JOINs: Bei einem INNER JOIN handelt es sich um eine gefilterte Form des CROSS JOINs, bei der in der Ergebnismenge nur die Tupel beider Ausgangstabellen zusammengeführt werden, die die vom Anwender definierte Selektionsbedingung erfüllen.
- OUTER JOINs: Der OUTER JOIN stellt eine Erweiterung des INNER JOINS dar. Ergebnismenge eines OUTER JOINS enthält die Tupel beider Ausgangstabellen, die die vom Anwender definierte Selektionsbedingung erfüllen, wie auch alle restlichen Tupel der ersten Tabelle, der zweiten Tabelle oder beider Tabellen. OUTER JOINS werden entsprechend als LEFT OUTER JOIN, RIGHT OUTER JOIN oder FULL OUTER JOIN realisiert.
- EQUI JOIN
- NON EQUI JOIN
- SELF JOIN
Die Selektionsbedingung eines EQUI JOINs ist somit immer die Gleichheit von Spalten-Werten.
Prinzipiell sind JOINS jedoch (ebenso wie die Selektion in der relationalen Algebra) nicht auf die Gleichheit von Spalten beschränkt. Mögliche Vergleichsoperatoren sind:
Vergleichsoperator | Bedeutung |
---|---|
= | gleich |
< | kleiner als |
> | größer als |
≤ | kleiner oder gleich |
≥ | größer oder gleich |
<> | ungleich |
!= | ungleich |
Das folgende Beispiel zeigt zwei unterschiedliche SQL-Statements, die zum selben Ergebnis führen. Im ersten Statement definieren wird die JOIN-Bedienung mithilfe des Schlüsselworts ON explizit. Beim zweiten Statement verwenden wir die Kurzschreibweise mit dem Schlüssel USING.
SELECT * FROM mitarbeiter INNER JOIN kfz ON mitarbeiter.kfz_id = kfz.kfz_id;
SELECT * FROM mitarbeiter INNER JOIN kfz USING kfz_id;
Werden zwei Tabellen über gleichnamige Spalten verknüpft, spricht man von einem NATURAL JOIN. Ein NATURAL JOIN wird über das gleichnamige Schlüsselwort standardmäßig als INNER JOIN realisiert. Auf diesen JOIN-Typ festgelegt sind NATURAL JOINs hingegen nicht. Möglich ist ebenso ein NATURAL LEFT OUTER JOIN oder ein NATURAL RIGHT OUTER JOIN.
Da die Verknüpfung bei NATURAL JOINs über gleichnamige Spalten erfolgt, werden die jeweiligen Werte in der Ergebnismenge nicht doppelt ausgegeben, sondern zu einer gemeinsamen Spalte zusammengeführt. Beispiele zu NATURAL JOINs finden Sie in den weiterführenden Artikeln zu INNER JOINs und OUTER JOINs.