- 1 Section
- 10 Lessons
- unbegrenzt
- SQL Fortgeschritten10
- 1.1Alle JOIN-Typen: RIGHT, FULL OUTER, CROSS, SELF
- 1.2Unterabfragen (Subqueries)
- 1.3Common Table Expressions (CTEs)
- 1.4Window Functions: ROW_NUMBER, RANK, PARTITION BY
- 1.5Views erstellen und nutzen
- 1.6Stored Procedures und Funktionen
- 1.7Trigger
- 1.8Datenbankindizes und Query-Optimierung
- 1.9Datenbankreporte und komplexe Auswertungen
- 1.10SQL-Fortgeschrittenenaufgaben
Alle JOIN-Typen: RIGHT, FULL OUTER, CROSS, SELF
In K35a L7 hast du INNER JOIN und LEFT JOIN kennengelernt – damit kommst du in 80 % der Fälle gut aus. Aber SQL bietet noch mehr JOIN-Varianten, und für Prüfungen wie für komplexere Auswertungen ist es wichtig, sie alle zu kennen.
Diese Lektion stellt dir das vollständige JOIN-Inventar vor: RIGHT JOIN, FULL OUTER JOIN, CROSS JOIN und SELF JOIN – plus ein paar Spezialfälle wie NATURAL JOIN und das USING-Schlüsselwort. Du verstehst, wann welcher JOIN sinnvoll ist und wie du sie in Klausuren erkennst.
1) Wiederholung: was macht ein JOIN?
Ein JOIN verknüpft Zeilen aus zwei Tabellen anhand einer Bedingung – meistens einer Fremdschlüssel-Beziehung. Statt Daten manuell zusammenzusuchen, lässt du die Datenbank das machen.
Beispiel-Szenario, das wir die ganze Lektion über verwenden: zwei Tabellen kunden und bestellungen:
| id | name |
|---|---|
| 1 | Anna |
| 2 | Ben |
| 3 | Carla |
| 4 | Dirk |
| id | kunde_id | artikel |
|---|---|---|
| 10 | 1 | Laptop |
| 11 | 1 | Maus |
| 12 | 2 | Tastatur |
| 13 | 5 | Monitor |
kunde_id = 5, die in der Kunden-Tabelle gar nicht existiert (z. B. nach Löschung des Kunden ohne Fremdschlüssel-Constraint). Diese „verwaisten" Zeilen werden bei den verschiedenen JOINs unterschiedlich behandelt.2) Überblick: die JOIN-Typen
SQL kennt im Wesentlichen sechs JOIN-Varianten. Du wählst je nach Frage, welche Zeilen behalten werden sollen, wenn auf der „anderen Seite" kein passender Eintrag existiert:
NULL.NULL.3) INNER JOIN – die Schnittmenge
Der INNER JOIN ist der häufigste Typ. Er liefert nur Zeilen zurück, für die in beiden Tabellen ein passender Eintrag existiert. Verwaiste Zeilen fallen weg:
SELECT k.name, b.artikel FROM kunden k INNER JOIN bestellungen b ON k.id = b.kunde_id;
| name | artikel |
|---|---|
| Anna | Laptop |
| Anna | Maus |
| Ben | Tastatur |
Das Schlüsselwort INNER ist optional – JOIN allein bedeutet immer INNER JOIN. Trotzdem solltest du es ausschreiben, weil es den Code lesbarer macht.
4) LEFT JOIN – alles aus der linken Tabelle
Der LEFT JOIN (auch LEFT OUTER JOIN) gibt alle Zeilen der linken Tabelle zurück. Für Zeilen ohne Treffer in der rechten Tabelle werden die rechten Spalten mit NULL gefüllt:
SELECT k.name, b.artikel FROM kunden k LEFT JOIN bestellungen b ON k.id = b.kunde_id;
| name | artikel |
|---|---|
| Anna | Laptop |
| Anna | Maus |
| Ben | Tastatur |
| Carla | NULL |
| Dirk | NULL |
LEFT JOIN ist perfekt für Fragen wie „Welche Kunden haben noch nichts bestellt?" – einfach WHERE b.id IS NULL ergänzen.5) RIGHT JOIN – Spiegelbild von LEFT JOIN
Der RIGHT JOIN ist das Spiegelbild: alle Zeilen der rechten Tabelle, links mit NULL gefüllt wenn nötig:
SELECT k.name, b.artikel FROM kunden k RIGHT JOIN bestellungen b ON k.id = b.kunde_id;
| name | artikel |
|---|---|
| Anna | Laptop |
| Anna | Maus |
| Ben | Tastatur |
| NULL | Monitor |
name = NULL. RIGHT JOIN ist nützlich, um „Bestellungen ohne gültigen Kunden" zu finden – ein typischer Datenqualitäts-Check.In der Praxis sieht man RIGHT JOIN selten. Die meisten Entwickler schreiben den JOIN um (Tabellen tauschen und LEFT JOIN nehmen), weil das natürlicher zu lesen ist. Funktional sind beide gleichwertig.
6) FULL OUTER JOIN – alle Zeilen aus beiden Tabellen
Der FULL OUTER JOIN kombiniert LEFT und RIGHT JOIN: alle Zeilen aus beiden Tabellen, fehlende Matches als NULL:
SELECT k.name, b.artikel FROM kunden k FULL OUTER JOIN bestellungen b ON k.id = b.kunde_id;
| name | artikel |
|---|---|
| Anna | Laptop |
| Anna | Maus |
| Ben | Tastatur |
| Carla | NULL |
| Dirk | NULL |
| NULL | Monitor |
NULL in einer Seite sind verdächtig.FULL OUTER JOIN wird von PostgreSQL, Oracle, SQL Server unterstützt, aber nicht von MySQL/MariaDB. Dort musst du ihn per LEFT JOIN UNION RIGHT JOIN nachbauen.
7) FULL OUTER JOIN in MySQL nachbauen
Da MySQL keinen FULL OUTER JOIN kennt, muss man ihn aus LEFT JOIN und RIGHT JOIN per UNION zusammensetzen:
SELECT k.name, b.artikel FROM kunden k LEFT JOIN bestellungen b ON k.id = b.kunde_id UNION SELECT k.name, b.artikel FROM kunden k RIGHT JOIN bestellungen b ON k.id = b.kunde_id;
UNION entfernt Duplikate automatisch. Wenn du Duplikate behalten möchtest, nimm UNION ALL. Das ist allerdings selten gewünscht.
8) CROSS JOIN – das kartesische Produkt
Der CROSS JOIN kombiniert jede Zeile der ersten Tabelle mit jeder Zeile der zweiten – ohne Bedingung. Das Ergebnis hat die Größe n × m:
SELECT k.name, b.artikel FROM kunden k CROSS JOIN bestellungen b;
| name | artikel |
|---|---|
| Anna | Laptop |
| Anna | Maus |
| Anna | Tastatur |
| Anna | Monitor |
| Ben | Laptop |
| Ben | Maus |
| … (insgesamt 4 × 4 = 16 Zeilen) | |
ON-Bedingung ist das ein riesiger Datenhaufen.Wann ist das sinnvoll? Eher selten – aber doch nützlich, z. B. um jede mögliche Kombination zu erzeugen (Größe × Farbe für Produktvarianten, Datum × Filiale für Reporting-Zeilen, jeder Wochentag × jeder Mitarbeiter für Schichtplanung).
FROM tabelle1, tabelle2 ohne WHERE-Bedingung schreibst (alte Komma-Syntax), entsteht ebenfalls ein kartesisches Produkt. Bei großen Tabellen ist das eine häufige Performance-Falle: aus 10.000 × 10.000 Zeilen werden 100 Millionen.
9) SELF JOIN – eine Tabelle mit sich selbst
Manchmal willst du Zeilen einer Tabelle mit anderen Zeilen derselben Tabelle verknüpfen. Klassisches Beispiel: eine Mitarbeiter-Tabelle, in der jeder Mitarbeiter einen Vorgesetzten hat (der wiederum ein Mitarbeiter ist):
| id | name | vorgesetzter_id |
|---|---|---|
| 1 | Eva (Chefin) | NULL |
| 2 | Felix | 1 |
| 3 | Gina | 1 |
| 4 | Hans | 2 |
Um zu jedem Mitarbeiter den Namen des Vorgesetzten anzuzeigen, joinst du die Tabelle mit sich selbst – über zwei verschiedene Aliase:
SELECT m.name AS mitarbeiter, v.name AS vorgesetzter FROM mitarbeiter m LEFT JOIN mitarbeiter v ON m.vorgesetzter_id = v.id;
| mitarbeiter | vorgesetzter |
|---|---|
| Eva (Chefin) | NULL |
| Felix | Eva (Chefin) |
| Gina | Eva (Chefin) |
| Hans | Felix |
m (der Mitarbeiter), einmal als v (der Vorgesetzte). Beide Aliase verweisen auf dieselbe physische Tabelle, sind aber logisch unabhängig. Hier mit LEFT JOIN, damit Eva trotz fehlendem Vorgesetzten erscheint.Weitere typische SELF-JOIN-Anwendungen:
- Hierarchien (Organigramm, Kategorien-Bäume, Kommentare mit Antworten)
- Vergleich zweier Zeilen in derselben Tabelle („Welche Produkte sind teurer als andere derselben Kategorie?")
- Paare finden („Welche Mitarbeiter teilen sich denselben Vorgesetzten?")
10) JOIN-Bedingungen: ON, USING, NATURAL JOIN
Du kennst die normale ON-Bedingung. Es gibt zwei abkürzende Schreibweisen, die du in Prüfungsaufgaben oder fremdem Code sehen kannst:
-- ON: explizit, am häufigsten verwendet SELECT * FROM a JOIN b ON a.id = b.a_id; -- USING: kurz, wenn Spalten gleich heißen SELECT * FROM a JOIN b USING (id); -- NATURAL JOIN: automatisch über alle gleichnamigen Spalten SELECT * FROM a NATURAL JOIN b;
Wann was?
ON: immer sicher, funktioniert mit beliebigen Bedingungen (auch>,<,BETWEEN). Standard-Empfehlung.USING: gut lesbar, wenn die Spalten in beiden Tabellen identisch heißen (typisch:id,kunde_id). Kommt aus dem SQL-Standard, von vielen DBs unterstützt.NATURAL JOIN: vermeiden. Verknüpft automatisch über alle gleichnamigen Spalten – wenn jemand später eine Spalte umbenennt, ändert sich die Bedeutung der Abfrage, ohne Vorwarnung. Sehr fehleranfällig.
11) Mehrere Tabellen kombinieren
JOINs lassen sich beliebig verketten. Stell dir vor, wir haben zusätzlich eine Tabelle artikel mit Preis und Kategorie und wollen eine vollständige Auswertung:
SELECT k.name, b.id AS bestellung, a.bezeichnung, a.preis FROM kunden k INNER JOIN bestellungen b ON k.id = b.kunde_id INNER JOIN artikel a ON b.artikel_id = a.id WHERE a.preis > 100 ORDER BY k.name, a.preis DESC;
Die JOINs werden von links nach rechts ausgeführt – aber die Datenbank kann den Plan optimieren (Reihenfolge ändern, Indizes nutzen). Wichtig für dich: jeder JOIN braucht eine eigene ON-Klausel, sonst entsteht ein versehentliches kartesisches Produkt.
12) JOIN vs. Subquery – wann was?
Vieles, was per JOIN geht, lässt sich auch per Subquery formulieren. Faustregel:
- JOIN, wenn du Spalten aus beiden Tabellen im Ergebnis brauchst
- Subquery, wenn du nur in einer Tabelle filtern willst (
WHERE x IN (SELECT …)) - EXISTS-Subquery, wenn du nur prüfen willst, ob es überhaupt einen Treffer gibt – oft schneller als
IN
Moderne Optimizer wandeln beide Varianten oft in denselben Ausführungsplan um. Du solltest aber wissen, dass es Alternativen gibt. Mehr dazu in L2 (Subqueries).
13) Häufige Fehler bei JOINs
Typische Stolperfallen in Klausuren und Praxis:
- WHERE statt ON bei OUTER JOINs:
LEFT JOIN … WHERE b.spalte = 'x'filtert die NULL-Zeilen wieder weg und macht den OUTER JOIN faktisch zum INNER JOIN. Die Bedingung gehört inON. - Mehrdeutige Spalten: wenn beide Tabellen eine Spalte
idhaben, brauchst du inSELECTeinen Tabellen-Präfix (k.idstatt nurid). - Vergessene Aliase beim SELF JOIN: ohne Aliase wird die Abfrage syntaktisch falsch.
- NULL-Falle:
NULL = NULLergibt nichtTRUE, sondernUNKNOWN. JOINs auf Spalten mit NULL-Werten verlieren diese Zeilen still. - Versehentliches kartesisches Produkt: vergessene
ON-Bedingung führt zu Millionen unsinniger Zeilen. - Reihenfolge ignoriert: bei
LEFT/RIGHT JOINist die Reihenfolge der Tabellen entscheidend, beimINNER/FULL OUTER/CROSSnicht.
INNER vs. LEFT JOIN gefragt – oder du musst zu einer gegebenen Frage den richtigen JOIN-Typ wählen. Achte auf Formulierungen wie „alle Kunden, auch ohne Bestellungen" – das ist klar LEFT JOIN.14) Performance-Hinweise
JOINs sind teuer, je nach Tabellengröße. Ein paar grundlegende Hinweise (Details in L8 Indizes & Query-Optimierung):
- Indizes auf JOIN-Spalten beschleunigen massiv.
kunde_idinbestellungensollte indiziert sein. - Filter früh anwenden: ein
WHERE, das eine Tabelle vorab kleiner macht, reduziert die JOIN-Last. - CROSS JOIN nur auf kleinen Tabellen. n × m wächst quadratisch.
- SELECT * vermeiden: nur die wirklich benötigten Spalten holen.
Zusammenfassung
SQL kennt sechs wichtige JOIN-Typen: INNER JOIN (Schnittmenge), LEFT/RIGHT JOIN (alle Zeilen einer Seite, fehlende Matches als NULL), FULL OUTER JOIN (alle Zeilen beider Seiten, nicht in MySQL), CROSS JOIN (kartesisches Produkt) und SELF JOIN (Tabelle mit sich selbst, über Aliase). Die JOIN-Bedingung steht in ON; alternativ USING bei gleichnamigen Spalten, NATURAL JOIN sollte vermieden werden. Wichtigster Fehler bei OUTER JOINs: Filter gehören in die ON-Klausel, nicht in WHERE – sonst werden die NULL-Zeilen wieder weggefiltert.
