Subqueries
Subqueries (Nested Queries)
Subqueries—also called nested queries—allow you to embed one query inside another. While they are expressive and widely supported, they tend to be harder to read, reuse, and optimize compared to CTEs. In modern engines (PostgreSQL, SQL Server, Snowflake, Databricks, BigQuery, Oracle), CTEs are almost always preferred from a readability and maintainability standpoint.
However, subqueries remain important, especially for inline filtering, simple tests of existence, correlated queries, and when targeting older engines with limited CTE support.
Why Subqueries Are Often Worse Than CTEs
Subqueries are not “terrible,” but they are inferior in several practical ways:
✅ CTEs Improve Readability and Maintainability
Subqueries nest logic deeply → harder to understand.
CTEs separate logic → readable step-by-step.
✅ CTEs Allow Reuse
A subquery can’t be referenced twice; a CTE can.
✅ CTEs Enable Greedy Optimization (in modern engines)
PostgreSQL (since v12), SQL Server, Oracle, BigQuery, Snowflake optimize CTEs similarly to subqueries.
Subqueries may be re-evaluated if the optimizer cannot guarantee reuse.
⚠️ Subqueries Can Have Performance Pitfalls
NOT INwithNULLproduces wrong results unless carefully guarded.Many engines struggle to optimize deeply nested subqueries.
Harder for the optimizer to “push down” predicates.
🎯 Best practice
Use subqueries only when they are the simplest expression of intent; otherwise use CTEs.
Types of Subqueries + Examples
1. IN Subqueries
These return a set of values for filtering.
Find customers who have placed orders
Find products in specific categories
2. NOT IN Subqueries (Be Careful!)
NOT IN ignores rows if the subquery returns NULL → often broken.
Find customers who never placed an order
3. Comparison Subqueries (ALL / ANY)
Employees who earn more than ANYONE in Marketing
Alternative using MAX()
4. EXISTS / NOT EXISTS (Most Efficient Filter Type)
EXISTS returns true as soon as one row matches—very efficient.
Basic EXISTS pattern
Find employees with no direct reports
5. Named Subqueries (Inline Views / Derived Tables)
You can name a subquery using AS to treat it like a temporary inline table.
Example
Another example using aggregation:
6. Nested Query Result Operators
ALL
Expression must be true for every value in the subquery
ANY
Expression must be true for at least one value
IN
Equivalent to = ANY(subquery)
EXISTS
True if the subquery returns at least one row
7. OLAP / Analytics Subquery Patterns
Regions that performed above average
Above-average regions using EXISTS
Last updated