SQL: a CTE names a subquery so the query reads top to bottom

WITH lets you build a query in named steps instead of nesting it inside out. In modern engines it is a readability change, not a performance one.

Code
WITH paid AS (
  SELECT * FROM orders WHERE status = 'PAID'
), per_customer AS (
  SELECT customer_id, SUM(total) AS spend FROM paid GROUP BY customer_id
)
SELECT c.name, p.spend
  FROM per_customer p JOIN customer c ON c.id = p.customer_id
 ORDER BY p.spend DESC
 LIMIT 10;
Output
-- PostgreSQL 11 and earlier ALWAYS materialised a CTE, which blocked the
-- planner from pushing filters into it. Since 12 it inlines by default.
--   WITH x AS MATERIALIZED     (...)  force the old behaviour
--   WITH x AS NOT MATERIALIZED (...)  force inlining
--
-- A CTE referenced twice is still computed once when materialised, which is
-- the one case where it beats a repeated subquery.
Advertisement

Run this yourself in the Online Java Compiler, spin up a live REST API in the API Sandbox, or practise with Java interview questions.

Published 2026-08-25