Skip to main content

Common Table Expressions

A Common Table Expression (CTE) is a named temporary result set within a single statement.

CTEs improve readability by decomposing queries into logical steps.

Core Concepts

CTE benefitWhy it helps
Named stepsEasier to read and review
Reuse in one queryAvoid repeated subquery text
Better structureClear pipeline of transformations
WITH category_totals AS (
SELECT category, SUM(amount) AS total_amount
FROM payments_agg
GROUP BY category
)
SELECT category, total_amount
FROM category_totals
ORDER BY total_amount DESC;
categorytotal_amount
tools300.0
cloud130.0

Code Examples

-- CTE replacing nested subquery style.
WITH avg_price AS (
SELECT AVG(price) AS value
FROM products_sub
)
SELECT p.product_id, p.name, p.price
FROM products_sub AS p, avg_price AS a
WHERE p.price > a.value
ORDER BY p.price DESC;
product_idnameprice
3Pro Keyboard150.0
2Keyboard100.0
-- CTE with aggregation and post-filter.
WITH city_counts AS (
SELECT city, COUNT(*) AS cnt
FROM contacts_count
GROUP BY city
)
SELECT city, cnt
FROM city_counts
WHERE cnt >= 2
ORDER BY city;
citycnt
Berlin2
Tokyo2

SQLite-Specific Nuances

SQLite Nuance

SQLite supports non-recursive and recursive CTEs.

Start with non-recursive CTEs for readability before introducing recursion.

Common Pitfalls / Best Practices

Pitfall

Using too many one-off CTE layers for simple queries, making SQL longer without clarity gains.

Best Practice

Use CTEs when they improve naming and readability of meaningful intermediate steps.

Quick Challenge

Write a CTE that computes average amount from payments_agg, then selects payments above that average.

View Solution
WITH avg_amount AS (
SELECT AVG(amount) AS value
FROM payments_agg
)
SELECT payment_id, category, amount
FROM payments_agg, avg_amount
WHERE amount > avg_amount.value
ORDER BY amount DESC;
payment_idcategoryamount
1tools120.0
5tools100.0