Question presented to candidate:
"I want every customer with their paid orders, including customers who have none. I wrote LEFT JOIN orders ... WHERE o.status = 'paid' and some customers vanished. Why? Does it matter whether a condition goes in the ON clause or the WHERE clause?"
What a strong answer should cover:
- For an INNER JOIN it does not matter: ON and WHERE give the same rows
- For a LEFT JOIN it matters: ON decides which right rows match; unmatched left rows are still kept and padded with NULLs. WHERE runs afterwards and removes rows, including those NULL-padded ones
- So a right-table filter in WHERE turns the LEFT JOIN into an inner join (PostgreSQL even plans it as a plain
Hash Join) - A left-table filter in ON does not remove left rows; it only stops them from matching. To filter the left table, use WHERE
WHERE o.status = 'paid' OR o.status IS NULLis not a fix: it keeps customers with no orders but still drops customers whose orders are all unpaid- The deliberate use of WHERE on the right table:
WHERE o.id IS NULLfor an anti-join
Code / implementation expected: Yes β the same LEFT JOIN with the filter in ON and in WHERE, and the different results.
Schema used by the examples: