Question presented to candidate:
"We need the customers who have never ordered. A colleague wrote WHERE id NOT IN (SELECT customer_id FROM orders) and it returns no rows at all, although Dara and Eli clearly have no orders. NOT EXISTS works. Explain exactly why, and how you would write it."
What a strong answer should cover:
- SQL uses three-valued logic: comparing with NULL gives UNKNOWN, and WHERE keeps only TRUE
x NOT IN (a, b, NULL)meansx <> a AND x <> b AND x <> NULL; the last term is UNKNOWN, so the whole predicate can never be TRUE and the query returns nothingNOT EXISTSonly asks whether a matching row exists; a NULL never matches, so it is simply ignored- The outer side matters too: a NULL outer value is excluded by
NOT INbut kept byNOT EXISTS - Fixes: prefer
NOT EXISTS; or filterWHERE customer_id IS NOT NULLin the subquery; orLEFT JOIN ... IS NULL; declare the columnNOT NULLif it should be - Performance: PostgreSQL turns
NOT EXISTSinto an anti join but keepsNOT INas a filter with a subplan, which degrades badly when the subquery does not fit in memory
Code / implementation expected: Yes β show NOT IN returning nothing and NOT EXISTS returning the right customers on data with one NULL.
Schema used by the examples: