Question presented to candidate: "We have a customers table and an orders table. Some customers never ordered, and a few orders point at a customer that is missing. Walk me through the join types SQL gives you, what each one returns for those rows, and when you would reach for each."
What a strong answer should cover:
- INNER JOIN keeps only matching pairs; LEFT / RIGHT OUTER JOIN also keep unmatched rows from one side, filled with NULLs; FULL OUTER JOIN keeps unmatched rows from both sides
- CROSS JOIN is every row paired with every row (a Cartesian product); a self join is a table joined to itself
- Joins multiply rows: a one-to-many join repeats the "one" side once per match, so aggregates and counts must account for it
- NULL join keys never match (NULL = NULL is not true), and unmatched rows are where NULLs appear in the output
- Anti-join and semi-join patterns: LEFT JOIN ... WHERE right.key IS NULL or NOT EXISTS for "rows with no match", EXISTS for "rows with at least one match"
- Engine support: SQLite has RIGHT and FULL OUTER JOIN only since 3.39.0; MySQL has no FULL OUTER JOIN
Code / implementation expected: Yes β write an INNER and a LEFT JOIN and say what happens to unmatched rows.
Schema used by the examples: