SQL / CHAPTER 05
Join tables without losing the question
IntermediatePredict row multiplication and preserve unmatched records.
By the end of this chapter
- Choose INNER or LEFT JOIN from the requirement
- Trace one-to-many output cardinality
- Place filters without accidentally removing unmatched rows
The idea
A join relates rows from two sources using a stated condition. An inner join retains matching pairs; a left join also retains each unmatched left row with NULL values on the right. Before writing the query, describe the expected relationship: one-to-one, one-to-many, or many-to-many. A parent with three matching children produces three joined rows, which matters when counting or summing.
Filter placement can change the meaning of an outer join. A right-side condition in ON restricts eligible matches while preserving unmatched left rows. Moving that condition into WHERE may remove those rows because their right-side values are NULL. Select explicit columns and use aliases to clarify ownership. Test a parent with several matches, one with only excluded matches, and one with none.
WITH teams(id,name) AS (VALUES(1,'A'),(2,'B')),
tasks(id,team_id,done) AS (VALUES(10,1,0),(11,1,1))
SELECT teams.name, tasks.id
FROM teams LEFT JOIN tasks
ON tasks.team_id=teams.id AND tasks.done=0
ORDER BY teams.id;name | id A | 10 B | NULL
The ON condition admits only unfinished tasks while the left join still preserves team B, which has no matching task.
Try it yourself
List every project with its open tasks, retaining projects with no open task.
Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.
Open SQL coding challengesCHECK YOUR UNDERSTANDING