SQL Joins erklärt: Typen, Beispiele und Übungen
Ein SQL JOIN verbindet zwei oder mehr Tabellen zur Laufzeit über gemeinsame Werte, ohne die Daten physisch zusammenzuführen. Das Ergebnis entsteht erst beim Ausführen der Abfrage. Welche Join-Typen gibt es?
SELECT k.name, b.betrag FROM kunden AS k INNER JOIN bestellungen AS b ON k.id = b.kunden_id;
Die wichtigsten Typen auf einen Blick:
- INNER JOIN – liefert nur Zeilen, die in beiden Tabellen übereinstimmen
- LEFT JOIN – alle Zeilen der linken Tabelle, fehlende rechte Seiten werden mit NULL aufgefüllt
- RIGHT JOIN – spiegelbildlich zum LEFT JOIN
- FULL OUTER JOIN – alle Zeilen beider Tabellen, nicht übereinstimmende Seiten erhalten NULL
- CROSS JOIN – kartesisches Produkt: jede Zeile der ersten Tabelle trifft auf jede Zeile der zweiten
- SELF JOIN – eine Tabelle wird mit sich selbst verbunden, über Aliase unterscheidbar
- NATURAL JOIN – automatische Verknüpfung über gleichnamige Spalten; in der Praxis selten empfohlen
Inhaltsverzeichnis
- Was ist ein SQL JOIN genau?
- Welche JOIN-Typen gibt es und wie unterscheiden sie sich?
- Ein durchgängiges Beispiel mit Kunden und Bestellungen
- Welche Fehler passieren beim Einsatz von JOINs am häufigsten?
- Wie macht man JOINs schneller?
- Wie schreibt man JOINs so, dass andere sie verstehen?
- Wie können Sie JOINs mit Logicexcel-Übungen trainieren?
- Schnellreferenz: Alle JOIN-Typen auf einen Blick
- Wichtige Erkenntnisse
- Jetzt SQL-JOINs auf Logicexcel üben
- Weiterführende Quellen zur Vertiefung
- FAQ
Was ist ein SQL JOIN genau?
Ein JOIN ist eine Verbundoperation in SQL), die Zeilen aus zwei oder mehr Tabellen anhand einer gemeinsamen Bedingung zusammenführt. Tabellen werden dabei nicht dauerhaft verändert; die Verknüpfung existiert nur für die Dauer der Abfrage.
Warum braucht man das überhaupt? Relationale Datenbanken speichern Daten normalisiert, also aufgeteilt auf mehrere Tabellen, um Redundanz zu vermeiden. Eine Kundentabelle enthält Kundendaten, eine Bestelltabelle enthält Bestelldaten. Der Fremdschlüssel bestellungen.kunden_id verweist auf den Primärschlüssel kunden.id. Genau diese Beziehung nutzt der JOIN.
Wichtige Voraussetzungen:
- Die verknüpften Spalten müssen denselben Datentyp haben, sonst entstehen implizite Typkonvertierungen mit unerwarteten Ergebnissen.
- Datenintegrität wird durch definierte Schlüsselbeziehungen unterstützt, ist aber keine zwingende Voraussetzung für einen JOIN.
- Auch ohne formalen Fremdschlüssel kann man joinen, solange die Werte übereinstimmen.
Welche JOIN-Typen gibt es und wie unterscheiden sie sich?
INNER JOIN
Liefert nur die Zeilen, bei denen die ON-Bedingung in beiden Tabellen erfüllt ist. Kunden ohne Bestellung erscheinen nicht im Ergebnis.
SELECT k.name, b.betrag
FROM kunden AS k
INNER JOIN bestellungen AS b ON k.id = b.kunden_id;
Venn-Diagramm: nur die Schnittmenge beider Kreise.
LEFT JOIN
Alle Zeilen der linken Tabelle bleiben erhalten. Hat ein Kunde keine Bestellung, erscheint er trotzdem, die Bestellspalten zeigen NULL.
SELECT k.name, b.betrag
FROM kunden AS k
LEFT JOIN bestellungen AS b ON k.id = b.kunden_id;
Venn-Diagramm: der gesamte linke Kreis plus die Schnittmenge.
RIGHT JOIN
Spiegelbildlich zum LEFT JOIN: alle Zeilen der rechten Tabelle bleiben erhalten. Viele Teams vermeiden RIGHT JOIN und tauschen stattdessen die Tabellenreihenfolge, um alles als LEFT JOIN zu schreiben. Das erhöht die Lesbarkeit.
FULL OUTER JOIN
Kombiniert alle Zeilen beider Tabellen. Wo kein Match existiert, füllt die Datenbank NULL ein. Nicht alle Datenbanksysteme unterstützen FULL OUTER JOIN direkt; in MySQL lässt er sich über UNION aus LEFT und RIGHT JOIN nachbauen.
SELECT k.name, b.betrag
FROM kunden AS k
FULL OUTER JOIN bestellungen AS b ON k.id = b.kunden_id;
Venn-Diagramm: beide Kreise vollständig, Schnittmenge einmal.
CROSS JOIN
Erzeugt ein kartesisches Produkt): jede Zeile der ersten Tabelle kombiniert mit jeder Zeile der zweiten. Keine ON-Bedingung. Bei 100 Kunden und 200 Produkten entstehen 20.000 Zeilen. Sinnvoll für Kombinationstabellen, gefährlich ohne Filter.
SELF JOIN
Kein eigener SQL-Befehl), sondern die Verwendung einer Tabelle zweimal in einer Abfrage über Aliase. Klassischer Anwendungsfall: eine Mitarbeitertabelle, in der eine Spalte vorgesetzter_id auf die eigene id-Spalte verweist.
SELECT m.name AS mitarbeiter, v.name AS vorgesetzter
FROM mitarbeiter AS m
LEFT JOIN mitarbeiter AS v ON m.vorgesetzter_id = v.id;
NATURAL JOIN
Verbindet automatisch über alle gleichnamigen Spalten. Praktisch, aber fehleranfällig bei Schemaänderungen): wird später eine neue Spalte mit gleichem Namen hinzugefügt, ändert sich das Verhalten der Abfrage still und leise. Besser: immer explizite ON-Klausel verwenden.
Vergleichstabelle der Join-Typen
| Join-Typ | Was bleibt erhalten | NULL-Zeilen möglich | Typische Fehlerquelle |
| INNER JOIN | Nur übereinstimmende Zeilen | Nein | Zeilen verschwinden unerwartet |
| LEFT JOIN | Alle Zeilen links | Ja, rechts | WHERE filtert NULLs weg |
| RIGHT JOIN | Alle Zeilen rechts | Ja, links | Verwirrende Leserichtung |
| FULL OUTER JOIN | Alle Zeilen beider Tabellen | Ja, beide Seiten | Nicht überall unterstützt |
| CROSS JOIN | Alle Kombinationen | Nein | Riesige Ergebnismengen |
| SELF JOIN | Abhängig vom Join-Typ | Ja (bei LEFT) | Fehlende oder falsche Aliase |
| NATURAL JOIN | Nur Übereinstimmungen | Nein | Unerwartete Spaltenpaare |
Ein durchgängiges Beispiel mit Kunden und Bestellungen
Ausgangstabellen:Tabelle kunden:
| id | name |
| 1 | Anna |
| 2 | Ben |
| 3 | Clara |
| 4 | David |
| id | kunden_id | betrag |
| — | 1 | — |
| — | 1 | — |
| — | 2 | — |
| 104 | 5 | — |
SELECT k.name, b.betrag
FROM kunden AS k
INNER JOIN bestellungen AS b ON k.id = b.kunden_id;
Anna erscheint zweimal, weil sie zwei Bestellungen hat. Das ist bei 1:n-Beziehungen korrekt. Clara und David fehlen, weil sie keine Bestellungen haben. Bestellung 104 fehlt, weil Kunde 5 nicht existiert.
LEFT JOIN:SELECT k.name, b.betrag
FROM kunden AS k
LEFT JOIN bestellungen AS b ON k.id = b.kunden_id;
| name | betrag |
| Clara | NULL |
| David | NULL |
SELECT m.name AS mitarbeiter, v.name AS vorgesetzter
FROM mitarbeiter AS m
LEFT JOIN mitarbeiter AS v ON m.vorgesetzter_id = v.id;
Ohne Aliase würde die Datenbank nicht wissen, welche Instanz der Tabelle gemeint ist. Der LEFT JOIN stellt sicher, dass auch Mitarbeiter ohne Vorgesetzten (z. B. die Geschäftsführung) im Ergebnis erscheinen.
Wichtige Beobachtungen:
- Bei 1:n-Beziehungen entstehen mehrere Zeilen pro Entität auf der „1“-Seite. Das ist kein Fehler.
- NULL in einer Ergebnisspalte bedeutet: kein passender Datensatz auf dieser Seite.
- Ein CROSS JOIN mit diesen vier Kunden und vier Bestellungen würde 16 Zeilen erzeugen.
Welche Fehler passieren beim Einsatz von JOINs am häufigsten?
Fehlende ON-Klausel führt zum kartesischen Produkt, also demselben Ergebnis wie ein CROSS JOIN. Vor dem Ausführen prüfen: Hat jeder JOIN ein ON? Gibt es eine WHERE-Bedingung als Notbremse?
WHERE statt ON bei OUTER JOINs ist einer der häufigsten Fehler überhaupt. WHERE filtert das fertige Ergebnis; ON definiert die Join-Bedingung. Wer bei einem LEFT JOIN eine Bedingung auf die rechte Tabelle in die WHERE-Klausel schreibt, entfernt damit alle NULL-Zeilen und macht den LEFT JOIN faktisch zu einem INNER JOIN.
-- Falsch: WHERE entfernt NULL-Zeilen
SELECT k.name, b.betrag
FROM kunden AS k
LEFT JOIN bestellungen AS b ON k.id = b.kunden_id
WHERE b.betrag > 50;
-- Richtig: Bedingung in ON
LEFT JOIN bestellungen AS b ON k.id = b.kunden_id AND b.betrag > 50
Nicht eindeutige Join-Spalten ohne Primärschlüssel erzeugen Duplikate. DISTINCT oder GROUP BY sind dann nur Pflaster; die eigentliche Lösung ist ein sauberes Schema.
Datentypkonflikte zwischen den verknüpften Spalten (z. B. VARCHAR gegen INT) lösen implizite Konvertierungen aus. Das kann zu falschen Matches oder schlechter Performance führen.
Spaltenname-Mehrdeutigkeit bei mehreren Joins: Ohne Tabellenqualifizierung weiß die Datenbank nicht, welche id gemeint ist. Aliase lösen das Problem.
Profi-Tipp: Führe vor einem komplexen JOIN zunächst SELECT COUNT() auf jeder Tabelle aus. Nach dem JOIN prüfst du, ob die Zeilenzahl plausibel ist. Mit LIMIT 10 siehst du schnell, ob NULLs oder Duplikate auftauchen, ohne das gesamte Ergebnis laden zu müssen.*
Wie macht man JOINs schneller?
Indizes auf den Join-Spalten sind der wichtigste Hebel. Ein Fremdschlüssel ohne Index zwingt die Datenbank, bei jedem JOIN die gesamte Tabelle zu durchsuchen. Primärschlüssel sind meist automatisch indiziert; Fremdschlüssel oft nicht.
SQL Server unterscheidet drei physische Join-Algorithmen: Nested Loops, Merge Join und Hash Join. Nested Loops eignen sich für kleine Tabellen oder wenn ein Index vorhanden ist. Merge Join arbeitet effizient, wenn beide Seiten bereits sortiert vorliegen. Hash Join kommt bei großen, unsortieren Tabellen ohne passenden Index zum Einsatz. Der Abfrageoptimierer wählt automatisch, aber EXPLAIN (bzw. SHOWPLAN in SQL Server) zeigt, welche Methode gewählt wurde und wo Kosten entstehen.Weitere Ansätze:
- Nur benötigte Spalten in SELECT aufnehmen, kein SELECT * bei Joins über große Tabellen.
- Filter früh setzen: eine WHERE-Bedingung, die Zeilen vor dem JOIN reduziert, spart Arbeit.
- Unnötige Joins vermeiden: Manchmal reicht eine Unterabfrage oder EXISTS.
Wie schreibt man JOINs so, dass andere sie verstehen?
Lesbarkeit beginnt mit Aliasen. FROM kunden AS k spart Tipparbeit und macht lange Abfragen übersichtlich. Konsistente Kürzel wie k für Kunden, b für Bestellungen und p für Produkte helfen, den Überblick zu behalten.
Die explizite JOIN...ON-Syntax ist heute Industriestandard. Die alte Komma-Notation (FROM kunden, bestellungen WHERE k.id = b.kunden_id) vermischt Join-Logik und Filterbedingungen und ist schwerer zu lesen.
Spalten immer mit Tabellenname qualifizieren, sobald mehr als eine Tabelle im Spiel ist:
SELECT k.name, b.betrag, p.bezeichnung
FROM kunden AS k
INNER JOIN bestellungen AS b ON k.id = b.kunden_id
INNER JOIN positionen AS p ON b.id = p.bestell_id
WHERE b.betrag > 50;
Wichtige Stilregeln:
- Jeden JOIN auf eine eigene Zeile setzen.
- ON-Bedingung direkt unter dem zugehörigen JOIN einrücken.
- WHERE-Klausel am Ende, klar getrennt von den Join-Bedingungen.
- Keine Mischung aus expliziter und alter Komma-Syntax in derselben Abfrage.
Wie können Sie JOINs mit Logicexcel-Übungen trainieren?
Theorie lesen reicht nicht. JOINs verstehen heißt, sie selbst zu schreiben und die Ergebnisse zu interpretieren. Logicexcel bietet kostenlose SQL-Übungen direkt im Browser, ohne Anmeldung und ohne Installation.
Empfohlene Lernschritte:
- Beispielabfragen aus diesem Artikel in der Übungsumgebung nachbauen.
- Den JOIN-Typ variieren: Aus INNER JOIN einen LEFT JOIN machen und beobachten, welche Zeilen hinzukommen.
- Absichtlich einen Fehler einbauen (z. B. WHERE statt ON) und das veränderte Ergebnis analysieren.
- Das Ergebnis interpretieren: Warum erscheinen NULL-Werte? Wie viele Zeilen entstehen bei einer 1:n-Beziehung?
Schnellreferenz: Alle JOIN-Typen auf einen Blick
| Join-Typ | Was bleibt | Beispiel-Syntax | Hinweis |
| INNER JOIN | Nur Matches | FROM a INNER JOIN b ON a.id = b.a_id | Standard, wenn kein Schlüsselwort angegeben |
| LEFT JOIN | Alle Zeilen links | FROM a LEFT JOIN b ON a.id = b.a_id | NULLs rechts bei fehlendem Match |
| RIGHT JOIN | Alle Zeilen rechts | FROM a RIGHT JOIN b ON a.id = b.a_id | Oft durch LEFT mit getauschter Reihenfolge ersetzt |
| FULL OUTER JOIN | Alle Zeilen beider Tabellen | FROM a FULL OUTER JOIN b ON a.id = b.a_id | In MySQL nicht direkt verfügbar |
| CROSS JOIN | Kartesisches Produkt | FROM a CROSS JOIN b | Kein ON; Ergebnis kann sehr groß werden |
| SELF JOIN | Abhängig vom Typ | FROM t AS t1 JOIN t AS t2 ON t1.chef_id = t2.id | Aliase zwingend erforderlich |
SELECT * FROM a LEFT JOIN b ON a.id = b.a_id
UNION
SELECT * FROM a RIGHT JOIN b ON a.id = b.a_id;
Wichtige Erkenntnisse
Der INNER JOIN liefert nur übereinstimmende Zeilen; für vollständige Datensätze aus einer Tabelle braucht man LEFT, RIGHT oder FULL OUTER JOIN.
| Thema | Details |
| ON vs. WHERE bei OUTER JOINs | Filterbedingungen auf die rechte Tabelle gehören in ON, nicht WHERE, sonst werden NULL-Zeilen entfernt. |
| 1:n-Beziehungen und Duplikate | Bei mehreren Bestellungen pro Kunde erscheint der Kunde mehrfach; GROUP BY löst das, nicht DISTINCT. |
| Indizes auf Join-Spalten | Fremdschlüssel ohne Index erzwingen einen vollständigen Tabellenscan; gezieltes Indizieren beschleunigt JOINs erheblich. |
| Aliase und explizite Syntax | Tabellenaliase und JOIN...ON trennen Join-Logik von Filterbedingungen und machen Abfragen wartbar. |
| Logicexcel zum Üben | Kostenlose, interaktive SQL-Übungen auf Logicexcel helfen, JOIN-Szenarien direkt im Browser zu trainieren. |
Ein letzter Gedanke zu JOINs
JOINs sind der Punkt, an dem viele Lernende aufgeben. Die Syntax sieht harmlos aus, aber das Verhalten bei NULL-Werten, 1:n-Beziehungen und falsch platzierten WHERE-Bedingungen überrascht selbst erfahrene Entwickler regelmäßig.
Was ich nach Jahren mit SQL für das Wichtigste halte: Wer JOINs wirklich versteht, denkt nicht mehr in Tabellen, sondern in Beziehungen. Der Unterschied zwischen ON und WHERE bei einem OUTER JOIN ist kein Detail. Er entscheidet darüber, ob eine Abfrage korrekte Ergebnisse liefert oder still und leise falsche Daten zurückgibt. Und genau das ist das Problem: Die Abfrage läuft durch, kein Fehler, kein Hinweis. Nur ein Ergebnis, das nicht stimmt.
Mein Rat: Schreib jede neue JOIN-Abfrage zuerst auf kleinen Testdaten. Prüfe die Zeilenzahl. Schau dir die NULL-Werte an. Dann erst auf den echten Datenbestand.
Jetzt SQL-JOINs auf Logicexcel üben
Wer JOINs wirklich beherrschen will, kommt um echte Übungsaufgaben nicht herum. Logicexcel bietet genau das: kostenlose, interaktive SQL-Aufgaben direkt im Browser, mit sofortigem Feedback zu jeder Antwort.
Die Übungen decken gezielt die Szenarien ab, die in diesem Artikel erklärt wurden: Kunden-Bestellungs-Verknüpfungen, Self-Join-Aufgaben und Fehlerdiagnose bei unerwarteten Ergebnissen. Keine Anmeldung, keine Installation. Einfach öffnen und loslegen. Starte jetzt mit den kostenlosen SQL-Übungen auf Logicexcel und wende das Gelernte direkt an.
Weiterführende Quellen zur Vertiefung
Wer tiefer einsteigen möchte, findet hier geprüfte Ressourcen:
- Join (SQL) auf Wikipedia) – solide Grundlagendefinition mit formaler Beschreibung aller Join-Typen; gut als Nachschlagewerk.
- Microsoft Learn: Joins in SQL Server – technische Dokumentation zu physischen Join-Algorithmen (Nested Loops, Merge, Hash) und EXPLAIN/Showplan; unverzichtbar für Performance-Fragen.
- LearnSQL.de: SQL JOIN-Typen erklärt – praxisorientierte Erklärung der vier Basis-Join-Typen mit Abbildungen; empfehlenswert für Einsteiger.
- Koenigshofen Blog: SQL JOINs verstehen – erklärt typische Fehler wie ON vs. WHERE bei OUTER JOINs mit konkreten Beispielen.
- DBGate SQL Joins Tutorial – behandelt explizite JOIN-Syntax und Lesbarkeit; nützlich für Entwickler, die bestehende Abfragen refaktorieren.
- Logicexcel SQL-Übungen – interaktive Aufgaben zum direkten Anwenden; kein Lesen, sondern Machen.
FAQ
Wann nehme ich INNER JOIN, wann LEFT JOIN?
INNER JOIN, wenn nur Datensätze mit Übereinstimmung in beiden Tabellen relevant sind. LEFT JOIN, wenn alle Zeilen der linken Tabelle erhalten bleiben sollen, auch ohne passenden Eintrag rechts.
Was passiert bei einem CROSS JOIN ohne WHERE-Bedingung?
Jede Zeile der ersten Tabelle wird mit jeder Zeile der zweiten kombiniert; das Ergebnis hat so viele Zeilen wie das Produkt beider Tabellengrößen. Ohne Filter kann das sehr schnell sehr groß werden.
Wie debugge ich einen JOIN mit unerwarteten Ergebnissen?
Zuerst SELECT COUNT(*) auf jeder Tabelle einzeln ausführen, dann nach dem JOIN. Stimmt die Zeilenzahl nicht, prüfe die ON-Bedingung und ob WHERE versehentlich NULL-Zeilen entfernt.
Was ist der Unterschied zwischen INNER JOIN und EXISTS?
INNER JOIN gibt Spalten aus beiden Tabellen zurück und kann Duplikate erzeugen. EXISTS prüft nur, ob ein passender Datensatz vorhanden ist, und gibt keine Spalten der zweiten Tabelle zurück. Bei 1:n-Beziehungen vermeidet EXISTS Duplikate.
Wo kann ich SQL JOINs kostenlos üben?
Logicexcel bietet interaktive SQL-Aufgaben direkt im Browser, ohne Anmeldung. Die Übungen decken JOIN-Szenarien mit sofortigem Feedback ab.