VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
LEFT JOIN keeps every row of the left
table whether it matched or not, which is how you answer the other question:
what did not match.
Open the client with mysql -u root -p sakila before you start.
How LEFT JOIN works
COLUMN_LIST with the columns you want, LEFT_TABLE with the table
every row of which you want to keep, RIGHT_TABLE with the one you are pulling
extra columns out of, and each COLUMN_NAME with the column on that side that
links them.
The server behaves as an inner join for the rows that match. For a left row
that matches nothing, it keeps the row anyway and fills every column of the
right table with NULL. LEFT OUTER JOIN is the same clause spelled out, and
the word OUTER adds nothing.
Examples
1) Keep the unmatched rows
Sakila has 6 languages and every film is English, so 5 languages match no film. An inner join drops them. This does not.2) List only the rows that matched nothing
AddWHERE on a column of the right table that can never be NULL in a real
match, and you have kept exactly the unmatched rows.
f.film_id is the primary key of film, so a matched row always has one. A
NULL there can only have come from the join filling in a row that matched
nothing. Test any NOT NULL column of the right table and the same reasoning
holds. The primary key is the safest choice, because it is NOT NULL on every
table.
3) The question this answers in practice
Not every film in the catalog is on a shelf.inventory holds the copies, so
a film with no inventory row is one nobody can rent.
LEFT JOIN plus
WHERE <right key> IS NULL, is how you find rows in one table with nothing
matching in another.
A filter in WHERE undoes the outer join
This is the mistake that costs people the most time withLEFT JOIN. Adding an
ordinary condition on the right table looks harmless.
f.title, then WHERE tests each row, and NULL LIKE 'ACADEMY%' is NULL rather than true, so WHERE drops them.
Move the same condition into ON and it becomes part of what counts as a
match.
LEFT JOIN, a condition on the right table belongs in ON,
and a condition on the left table belongs in WHERE. The one deliberate
exception is IS NULL in example 2, where dropping the matched rows is the
whole point.
Summary
- Use
LEFT JOINto keep every row of the left table, matched or not. - Expect NULL in every right-hand column of a row that matched nothing.
- Test a
NOT NULLcolumn of the right table withIS NULLto list only the unmatched rows. - Put a condition on the right table in
ON, because inWHEREit drops the unmatched rows. - Read
LEFT OUTER JOINas another spelling of the same clause.
See also
- INNER JOIN — the join that keeps only matches
- RIGHT JOIN — the same idea from the other side
- IS NULL — the test that makes the unmatched rows visible
- EXISTS — the same question asked without a join
- MySQL JOIN performance and common mistakes — the same trap, seen as a bug report

