SQL LEFT JOIN: Zeilen mit optionalen Treffern
SQL LEFT JOIN gibt jede Zeile aus der linken Tabelle zurück und ergänzt passende Zeilen aus der rechten Tabelle. Fachlich ist das ein SQL OUTER JOIN: Gibt es keinen Treffer, werden die rechten Spalten mit NULL gefüllt. Nutze ihn, wenn du alle Datensätze einer Tabelle brauchst, unabhängig davon, ob verknüpfte Daten existieren, zum Beispiel alle Kunden mit oder ohne Bestellung. LEFT JOIN und LEFT OUTER JOIN sind identische Schlüsselwörter; OUTER ist optional.
SQL LEFT JOIN Beispiel zum Zurückgeben aller Zeilen
Ausgabe:
Die Ausgabe erscheint hier...
Ausgabe:
+------+--------------+
| name | gesamtbetrag |
+------+--------------+
| Alma | 79 |
| Alma | 150 |
| Ben | NULL |
| Cara | 45 |
+------+--------------+
4 row(s)
So funktioniert dieses Beispiel
kundenenthält drei Personen,bestellungenenthält drei Bestellungen, verknüpft überkunden_id.LEFT JOIN bestellungen b ON b.kunden_id = k.idpaart jeden Kunden mit jeder Bestellung, die zu seineridpasst. Alma hat zwei Bestellungen und erzeugt deshalb zwei Ergebniszeilen.- Ben hat keine Bestellungen. LEFT JOIN behält seine Zeile und setzt
b.gesamtbetragauf NULL, statt ihn aus dem Ergebnis zu entfernen (das würde INNER JOIN tun). ORDER BY k.id, b.idhält die Ausgabe pro Kunde gruppiert und innerhalb jedes Kunden stabil. Das NULL in Bens Spaltegesamtbetragsignalisiert das Fehlen eines Treffers statt einer Bestellung mit dem Wert 0.
ON vs WHERE: Warum die Position des Filters wichtig ist
Ein Filter auf die rechte Tabelle in WHERE statt in ON ist der häufigste LEFT-JOIN-Fehler. Er macht aus dem OUTER JOIN stillschweigend einen INNER JOIN.
-- Falsch: WHERE entfernt Ben, weil sein b.gesamtbetrag NULL ist
SELECT k.name, b.gesamtbetrag
FROM kunden k
LEFT JOIN bestellungen b ON b.kunden_id = k.id
WHERE b.gesamtbetrag > 50;
-- Richtig: ON filtert beim Join-Matching, Ben bleibt mit NULLs erhalten
SELECT k.name, b.gesamtbetrag
FROM kunden k
LEFT JOIN bestellungen b ON b.kunden_id = k.id AND b.gesamtbetrag > 50;
ON-Bedingungen werden während des Joins ausgewertet: nicht passende linke Zeilen erscheinen weiterhin mit NULLs. WHERE läuft nach dem Join und filtert jede Zeile heraus, in der die rechte Spalte NULL ist. Genau diese Zeilen soll LEFT JOIN eigentlich erhalten.
Anti-Join: Zeilen ohne Treffer finden
LEFT JOIN kombiniert mit einer IS NULL-Prüfung auf eine rechte Spalte ist ein Standardmuster, um fehlende verknüpfte Datensätze zu finden:
SELECT k.name
FROM kunden k
LEFT JOIN bestellungen b ON b.kunden_id = k.id
WHERE b.id IS NULL;
Das gibt nur Ben zurück, den Kunden ohne Bestellungen. Das Muster funktioniert, weil b.id nur für nicht passende linke Zeilen NULL ist. NOT EXISTS liefert dasselbe Ergebnis und ist oft klarer, wenn du keine rechten Spalten im Output brauchst.
LEFT JOIN vs INNER JOIN
| LEFT JOIN | INNER JOIN |
|---|---|
| Alle linken Zeilen, NULLs für nicht passende rechte Spalten | Nur Zeilen mit Treffer auf beiden Seiten |
| Zeilenanzahl mindestens so groß wie die linke Tabelle | Zeilenanzahl höchstens so groß wie die kleinere Tabelle |
| Verwenden, wenn nicht passende Zeilen Bedeutung haben (Reports, Vollständigkeitsprüfungen) | Verwenden, wenn jede Ergebniszeile gültige Daten aus beiden Tabellen haben muss |
Regel: Starte mit LEFT JOIN, wenn alle linken Zeilen erhalten bleiben müssen. Wechsle zu INNER JOIN, wenn nicht passende Zeilen irrelevant oder ungültig sind.
Häufige Fehler mit SQL LEFT JOIN
Zeilenvervielfachung bei One-to-Many-Joins
LEFT JOIN erzeugt eine Ergebniszeile pro passendem Paar. Hat ein Kunde zehn Bestellungen, erscheint dieser Kunde zehnmal. Wer aggregiert, ohne das zu berücksichtigen, bläht Summen auf.
-- Falsch: zählt Bestellzeilen, nicht Kunden
SELECT COUNT(*) FROM kunden k
LEFT JOIN bestellungen b ON b.kunden_id = k.id;
-- Richtig: zählt unterschiedliche Kunden
SELECT COUNT(DISTINCT k.id) FROM kunden k
LEFT JOIN bestellungen b ON b.kunden_id = k.id;
SELECT * bei Joins verwenden
SELECT * in einer Join-Abfrage liefert doppelte Spaltennamen (sowohl k.id als auch b.id), was in Anwendungscode zu Verwechslungen führt. Liste immer nur die Spalten auf, die du brauchst.
Performance-Hinweise
Indexiere den Join-Schlüssel der rechten Tabelle (bestellungen.kunden_id), damit die Engine Treffer nachschlagen kann, statt zu scannen. Ist die rechte Tabelle groß und nur ein Teil der Zeilen relevant, filtere vorab mit einer Unterabfrage oder verschiebe den Filter in die ON-Klausel, nicht in WHERE. So reduzierst du Join-Arbeit und behältst LEFT-JOIN-Semantik.
FAQ
Was ist der Unterschied zwischen LEFT JOIN und LEFT OUTER JOIN?
Keiner. LEFT JOIN und LEFT OUTER JOIN sind Synonyme im SQL-Standard. Jede große Datenbank (PostgreSQL, MySQL, SQLite, SQL Server, Oracle) behandelt beide identisch. Die meisten Entwickler lassen OUTER aus, weil es kürzer ist.
Warum liefert mein LEFT JOIN nach einer WHERE-Klausel weniger Zeilen?
Ein WHERE-Filter auf eine rechte Spalte entfernt NULL-erweiterte Zeilen und macht den LEFT JOIN effektiv zu einem INNER JOIN. Verschiebe die Bedingung in die ON-Klausel, damit nicht passende linke Zeilen im Ergebnis bleiben.
Wann sollte ich LEFT JOIN statt INNER JOIN verwenden?
Verwende LEFT JOIN, wenn linke Zeilen immer im Ergebnis stehen müssen, unabhängig von Treffern, etwa bei Vollständigkeitsreports, Missing-Data-Checks und optionaler Anreicherung. Verwende INNER JOIN, wenn nur passende Zeilen gültig sind und nicht passende ausgeschlossen werden sollen.