CTEs vs Subqueries: When to Use Each and Why It Matters
Common Table Expressions improve readability but the performance story is more nuanced than most articles admit.
Ameer Abdullah
Data Science Graduate · AI/ML & Data Science
Concept in Simple Words: A subquery is a query nested inside another (e.g., in FROM or WHERE). A Common Table Expression (CTE) is defined using the `WITH` keyword at the top. Think of a CTE as a named temporary result set. It makes code readable by structuring query logic top-down, instead of nested inside-out.
Deep Walkthrough & Code: Let's look at a CTE comparing regional sales performance against a subquery equivalent:
WITH RegionalSales AS ( SELECT region, SUM(amount) as sales FROM orders GROUP BY region ) SELECT * FROM RegionalSales WHERE sales > 50000;
Step-by-Step Dry Run: When execution starts, the query optimizer resolves RegionalSales first: aggregating order values per region. Then, the main query executes, filtering regions with sales > 50000. It behaves like a temporary table, but only exists for the duration of the query.
Production Level Issue & Fix: In older database engines (and PostgreSQL before version 12), CTEs acted as optimization barriers, meaning the engine would materialize (compute and write to disk) the CTE completely before filtering. The production fix in older Postgres versions is to use the `NOT MATERIALIZED` hint to allow the optimizer to push filters down into the CTE for better performance: `WITH RegionalSales AS NOT MATERIALIZED (...)`.
Practice what you just learned
Apply these concepts in PyCodeIt's interactive sandbox with real problems.
Open SQL Sandbox