Relationships and joins
INNER JOIN and LEFT JOIN
Choose whether a query should keep only matching rows or every row from the left table.
Suppose authors contains Ada and Lin, but only Ada has a post titled “Learning SQL”.
An inner join returns matching pairs:
SELECT authors.name, posts.title
FROM authors
INNER JOIN posts ON posts.author_id = authors.id;
The result contains Ada and her post. Lin disappears because no post row matches.
A left join keeps every row from the left table:
SELECT authors.name, posts.title
FROM authors
LEFT JOIN posts ON posts.author_id = authors.id;
Lin now appears with a NULL title. That NULL was produced by the missing match. It is not a stored post.
Use an inner join when the result requires related rows. Use a left join when the absence is meaningful, such as finding authors with no posts:
SELECT authors.name
FROM authors
LEFT JOIN posts ON posts.author_id = authors.id
WHERE posts.id IS NULL;
That returns Lin.
Be careful when filtering the right table. This condition removes NULL matches and effectively turns the left join into an inner join:
WHERE posts.status = 'published'
When the requirement is “all authors, plus their published posts,” place that condition in the join:
LEFT JOIN posts
ON posts.author_id = authors.id
AND posts.status = 'published'
One-to-many joins can return several rows for one author. That is correct when the author has several posts. Do not add DISTINCT automatically. The extra rows are real data, not a bug.
The table on the left side of the join is the one a left join preserves. Swap the table order and you change which rows survive with NULL matches.
Inner joins are the default when you write JOIN without a qualifier. INNER JOIN and JOIN mean the same thing in standard SQL. I use INNER JOIN in teaching examples because the intent is explicit.
Try this on your own: run both joins with one author who has no posts. Then move a right-table filter between WHERE and ON and explain the changed result.
Lesson completed