CHAPTER 20
Named subqueries that make complex logic readable.
Each employee's salary vs their department average
WITH dept_avg AS (
SELECT department, AVG(salary) AS avg_sal
FROM employees
GROUP BY department
)
SELECT e.name, e.salary, d.avg_sal,
e.salary - d.avg_sal AS diff
FROM employees e
JOIN dept_avg d ON e.department = d.department
ORDER BY e.department, diff DESC;Customer tier classification
WITH
order_totals AS (
SELECT customer_id, COUNT(*) AS orders, SUM(total) AS spent
FROM orders GROUP BY customer_id
),
customer_tier AS (
SELECT customer_id, spent,
CASE WHEN spent > 100000 THEN 'VIP'
WHEN spent > 10000 THEN 'Regular'
ELSE 'New' END AS tier
FROM order_totals
)
SELECT c.name, t.spent, t.tier
FROM customers c
JOIN customer_tier t ON c.customer_id = t.customer_id
ORDER BY t.spent DESC;✅ Pro Tips: Rule of thumb: if you need to reference the same subquery twice, use a CTE. If a subquery is used once and is simple, inline it. If it is used 3+ times, consider a view or temp table.
💡 Engineering Insight: CTEs do not always improve performance — in some databases they are materialised (computed once and cached), in others they are inlined as subqueries. PostgreSQL inlines by default; you can force materialisation with the MATERIALIZED keyword. Always check your EXPLAIN plan.
| order_id | customer_id | order_date | total | status |
|---|---|---|---|---|
| 1 | 1 | 2024-01-15 | 79999 | completed |
| 2 | 2 | 2024-01-20 | 3498 | completed |
| 3 | 1 | 2024-02-10 | 65000 | completed |
| 4 | 3 | 2024-02-14 | 499 | pending |
| 5 | 2 | 2024-03-01 | 248 | completed |
| 6 | 5 | 2024-03-15 | 2999 | shipped |
| 7 | 1 | 2024-04-05 | 149 | completed |
| customer_id | name | city | country |
|---|---|---|---|
| 1 | Ananya | Hyderabad | India |
| 2 | Rohan | Bangalore | India |
| 3 | Sam | Mumbai | India |
| 4 | Lisa | London | UK |
| 5 | Ravi | Delhi | India |
| item_id | order_id | product_id | qty | unit_price |
|---|---|---|---|---|
| 1 | 1 | 1 | 1 | 79999 |
| 2 | 2 | 3 | 1 | 2999 |
| 3 | 2 | 2 | 1 | 499 |
| 4 | 3 | 5 | 1 | 65000 |
| 5 | 4 | 2 | 1 | 499 |
| 6 | 5 | 4 | 2 | 99 |
| 7 | 5 | 6 | 1 | 50 |
| 8 | 6 | 3 | 1 | 2999 |
| product_id | name | category | price | stock |
|---|---|---|---|---|
| 1 | iPhone 15 | Electronics | 79999 | 50 |
| 2 | SQL Book | Books | 499 | 200 |
| 3 | Headphones | Electronics | 2999 | 75 |
| 4 | Notebook | Stationery | 99 | 500 |
| 5 | Laptop | Electronics | 65000 | 20 |
| 6 | Pen Set | Stationery | 149 | 0 |
| 7 | Mouse | Electronics | 599 | 25 |