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.
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;
-- 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.
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