A JOIN combines rows from two tables into one result, matching them on a shared key. The join type decides what happens to rows that find no partner.
Where you meet it
- Any query that spans more than one table — orders with their customers, posts with their authors.
- Reporting: "list every user and their order count, including users with zero orders."
- Data cleaning — finding rows in one table that have no match in another.
What it does
Relational data is deliberately split across tables to avoid repeating it. A join reassembles it on demand: it pairs each row of the left table with matching rows of the right table, following the rule you give in ON.
The join type is just a rule for partnerless rows — and a WHERE on the right table quietly turns your LEFT JOIN back into an INNER one.
How it works
The ON condition is checked for every possible pair of rows. Pairs where it's true become result rows. What sets the join types apart is how they treat rows with no match:
- INNER — keeps only matched pairs. Unmatched rows on either side disappear.
- LEFT — keeps every left row; right columns become
NULLwhen there's no match. RIGHT is the mirror; FULL OUTER keeps unmatched rows from both sides. - CROSS — no
ONat all: every left row paired with every right row (the Cartesian product).
-- users(id, name), orders(id, user_id, item)
SELECT u.name, o.item
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;
-- INNER drops Dan (no order) and order #105 (no user).
-- LEFT keeps Dan, with item = NULL.
Watch out
- No
ON→ accidental Cartesian product. Forgetting the condition (or a comma-join with noWHERE) pairs every row with every other — millions of rows from a small slip. - LEFT JOIN + a
WHEREon the right table silently becomes an INNER JOIN. A filter likeWHERE o.status = 'paid'rejects theNULLrows you were trying to keep. Put that condition in theONclause instead. - Duplicate rows from one-to-many. If one left row matches several right rows, the left row repeats once per match — easy to over-count in a
SUMorCOUNT.
Go deeper
Ein JOIN verbindet Zeilen aus zwei Tabellen zu einem Ergebnis und matcht sie über einen gemeinsamen Schlüssel. Der Join-Typ entscheidet, was mit partnerlosen Zeilen passiert.
Wo es vorkommt
- Jede Abfrage über mehr als eine Tabelle — Bestellungen mit ihren Kunden, Posts mit ihren Autoren.
- Auswertungen: "alle User und ihre Order-Anzahl, auch User mit null Orders."
- Datenbereinigung — Zeilen finden, die in einer anderen Tabelle keinen Match haben.
Was es tut
Relationale Daten liegen bewusst auf Tabellen verteilt, um Wiederholung zu vermeiden. Ein Join setzt sie auf Abruf wieder zusammen: Er paart jede Zeile der linken Tabelle mit passenden Zeilen der rechten — nach der Regel, die du in ON angibst.
Der Join-Typ ist nur eine Regel für partnerlose Zeilen — und ein WHERE auf der rechten Tabelle macht aus deinem LEFT JOIN heimlich wieder einen INNER.
Wie es funktioniert
Die ON-Bedingung wird für jedes mögliche Zeilenpaar geprüft. Paare, bei denen sie wahr ist, werden Ergebniszeilen. Die Join-Typen unterscheiden sich darin, wie sie Zeilen ohne Match behandeln:
- INNER — behält nur Treffer-Paare. Partnerlose Zeilen auf beiden Seiten fallen weg.
- LEFT — behält jede linke Zeile; rechte Spalten werden
NULL, wenn kein Match existiert. RIGHT ist das Spiegelbild; FULL OUTER behält partnerlose Zeilen beider Seiten. - CROSS — gar kein
ON: jede linke Zeile mit jeder rechten (das kartesische Produkt).
-- users(id, name), orders(id, user_id, item)
SELECT u.name, o.item
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;
-- INNER wirft Dan (keine Order) und Order #105 (kein User) raus.
-- LEFT behält Dan, mit item = NULL.
Worauf achten
- Kein
ON→ versehentliches kartesisches Produkt. Fehlt die Bedingung (oder Komma-Join ohneWHERE), wird jede Zeile mit jeder gepaart — aus einem kleinen Versehen werden Millionen Zeilen. - LEFT JOIN +
WHEREauf der rechten Tabelle wird heimlich zum INNER JOIN. Ein Filter wieWHERE o.status = 'paid'verwirft genau dieNULL-Zeilen, die du behalten wolltest. Setz die Bedingung stattdessen in dieON-Klausel. - Doppelte Zeilen durch 1:n. Matcht eine linke Zeile mehrere rechte, wiederholt sie sich einmal pro Match — schnell verzählt man sich in
SUModerCOUNT.