VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
INNER JOIN keeps a row only when the match succeeds. It is the join you want
whenever a row in one table points at a row in another and you want both.
Open the client with mysql -u root -p sakila before you start.
How INNER JOIN works
COLUMN_LIST with the columns you want, LEFT_TABLE with the table you
start from, 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 ON clause says which rows belong together. MySQL takes each row of the
left table, finds the rows of the right table where that condition holds, and
returns 1 combined row for each match. A row that finds nothing is dropped, on
either side. LEFT JOIN is the clause that keeps it
instead.
Examples
1) Join 2 tables
film.language_id points at language.language_id. Match that pair and you
can print the language name beside the title.
film on its own. Every film matched exactly 1
language, which is what you get when the joining column points at a single row.
2) Join across a foreign key
Customers keep their street address in a separate table.3) Join 3 tables
Add anotherINNER JOIN clause for each further table. Sakila splits location
across address, city and country, so reaching the city name takes 2 hops.
4) Shorten it with USING
When the 2 columns carry the same name,USING replaces ON and says the name
once.
USING works only when the names match on
both sides, so ON is the form that always applies.
Matching several rows multiplies them
A join returns 1 row per match, so a row that matches many rows comes back many times. Each film has several actors.2 things that catch people out
An unmatched row is gone, not blank. Start fromlanguage instead of
film and you still get 1,000 rows, not 1,005: Sakila’s other 5 languages
match no film and drop out. An inner join reports what matched, never what is
missing. LEFT JOIN is how you ask the other question.
A missing ON is not an error. MySQL reads INNER JOIN with no ON as
every combination of both tables, so a typo returns 1,000 times 6 rows rather
than a complaint. CROSS JOIN covers that, deliberate
and accidental.
Summary
- Use
INNER JOINwithONto combine rows from tables that match. - Add 1
INNER JOINclause per further table. - Expect unmatched rows to vanish, because an inner join reports only matches.
- Expect the row count to grow when 1 row matches many.
- Use
USINGonly when the column has the same name on both sides.
See also
- How joins work — what separates this from the other kinds
- LEFT JOIN — keeping the rows this one drops
- MySQL JOIN performance and common mistakes — indexing a join, and the row counts that come out wrong
- Foreign keys in MySQL — the relationships these joins follow

