WITH monthly AS (SELECT …) SELECT … FROM monthly works like creating a temporary table for one query.
Chain several CTEs, separated by commas, to stage the logic: first clean, then aggregate, then compare.
Worked example
What was paid revenue per month, and which months were above €3,000?
WITH monthly AS (
SELECT strftime('%Y-%m', invoice_date) AS month, SUM(amount) AS revenue
FROM invoices
WHERE status = 'paid'
GROUP BY month
)
SELECT month, revenue
FROM monthly
WHERE revenue > 3000
ORDER BY month
LIMIT 6;| month | revenue |
|---|---|
| 2025-12 | 4739 |
| 2026-01 | 3989 |
| 2026-02 | 5382 |
| 2026-03 | 5333 |
| 2026-04 | 5731 |
| 2026-05 | 4932 |
Common mistakes
- Forgetting the comma between two CTEs.
- Ending the CTE without a final SELECT that uses it.