← Back to PostgreSQL Course | Chapter 8: Subqueries & CTEs | Lesson 5 of 7

WITH (CTE)

A CTE names a subquery with WITH so you can reuse it and read queries top to bottom.

In this page:

  1. WITH (CTE)
Syntax
sql
WITH cte_name AS (
  SELECT columns FROM table_name WHERE condition
)
SELECT columns FROM cte_name;

WITH (CTE)

WITH name AS (SELECT ...) defines a temporary named result that the main query can reference, even several times. Multiple CTEs are separated by commas and can reference earlier ones.

CTEs make complex queries readable. Since PostgreSQL 12 they are inlined when referenced once, unless MATERIALIZED is specified.

Note: Use MATERIALIZED or NOT MATERIALIZED to control CTE optimisation in PostgreSQL 12 and later.

Example: WITH (CTE)

sql
CREATE TABLE orders (id INTEGER PRIMARY KEY, customer TEXT, total INTEGER);
INSERT INTO orders VALUES (1,'Ada',50),(2,'Bob',20),(3,'Ada',70),(4,'Cy',10),(5,'Bob',95);
WITH totals AS (SELECT customer, SUM(total) AS spent FROM orders GROUP BY customer),
     big AS (SELECT customer, spent FROM totals WHERE spent >= 100)
SELECT customer, spent FROM big ORDER BY spent DESC;

-- Output:
-- customer | spent
-- Ada | 120
-- Bob | 115
Related Topics
Common Mistakes
  1. Assuming CTEs are always materialised
  2. Using CTEs for tiny queries that add noise
  3. Forgetting the comma between CTEs
Chapter Summary
  • WITH name AS (query)
  • Reusable by the main query
  • Several CTEs are comma separated
  • Improves readability
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.