advanced
EXISTS and NOT EXISTS
Test whether a subquery returns any rows, a fast, set-based way to filter.
6 min read
Explanation
EXISTS checks whether a subquery returns at least one row. It doesn't care
about the values, only whether any row exists. That makes it ideal for
"find rows that have (or don't have) a related row somewhere else" questions.
NOT EXISTS is the negative form: "find rows where no related row exists."
Crucially, EXISTS is correlated, the subquery references the outer query
and is evaluated per outer row, stopping as soon as it finds a match.
EXISTS ignores the SELECT list
Write SELECT 1 or SELECT * inside EXISTS, the columns don't matter, only
the presence of a row does.
Syntax
SELECT col
FROM table_a a
WHERE EXISTS (
SELECT 1 FROM table_b b WHERE b.key = a.key
);Interactive Example
Find customers who have placed at least one order. Then find customers who have
not placed any order using NOT EXISTS.
Common Mistakes
- Using
=with EXISTS. EXISTS is a boolean test, not a value, never writeWHERE x = EXISTS (...). - Reaching for NOT IN with NULLs.
NOT IN (subquery)returns nothing if the subquery has a NULL; preferNOT EXISTS. - Selecting heavy columns inside EXISTS. It's wasted work;
SELECT 1is the convention.
Best Practices
- Use
EXISTSfor "has related rows" checks against large tables. - Prefer
NOT EXISTSoverNOT INto avoid NULL pitfalls. - Add the join condition (
b.key = a.key) so the subquery is properly correlated.
Practice Question
Using EXISTS, list products (products table) that have never been ordered,
i.e. no orders row references that product_id.
Summary
EXISTS returns true if a correlated subquery yields any row, making it a fast,
NULL-safe way to test relationships. NOT EXISTS is the reliable choice for
"does not appear" conditions.
FAQ
Cite this resource
SQLSimplified. "EXISTS and NOT EXISTS". Available at: https://sqlsimplified.online/learn/exists