#1 Data Analytics Program in India
₹2,499₹1,499Enroll Now
5 min read
Question 16 of 29medium

What are CTEs (Common Table Expressions)?

Temporary named result sets.

What You'll Learn

  • What CTEs are
  • Basic and recursive CTEs
  • Benefits over subqueries

What is a CTE?

A CTE is a temporary named result set that exists within the scope of a single statement.

Basic CTE

query.sqlSQL
WITH active_users AS (
  SELECT id, name, email
  FROM users
  WHERE status = 'active'
)
SELECT * FROM active_users WHERE name LIKE 'J%';

Multiple CTEs

query.sqlSQL
WITH
  active_users AS (
    SELECT * FROM users WHERE status = 'active'
  ),
  user_orders AS (
    SELECT user_id, COUNT(*) as order_count, SUM(total) as total_spent
    FROM orders
    GROUP BY user_id
  )
SELECT
  u.name,
  uo.order_count,
  uo.total_spent
FROM active_users u
JOIN user_orders uo ON u.id = uo.user_id
ORDER BY uo.total_spent DESC;

Recursive CTE

query.sqlSQL
-- Employee hierarchy
WITH RECURSIVE emp_hierarchy AS (
  -- Base case: top-level managers
  SELECT id, name, manager_id, 0 AS level
  FROM employees
  WHERE manager_id IS NULL

  UNION ALL

  -- Recursive case: employees with managers
  SELECT e.id, e.name, e.manager_id, h.level + 1
  FROM employees e
  JOIN emp_hierarchy h ON e.manager_id = h.id
)
SELECT * FROM emp_hierarchy ORDER BY level, name;

-- Generate number series
WITH RECURSIVE numbers AS (
  SELECT 1 AS n
  UNION ALL
  SELECT n + 1 FROM numbers WHERE n < 10
)
SELECT * FROM numbers;

CTE vs Subquery

query.sqlSQL
-- CTE (more readable)
WITH order_totals AS (
  SELECT user_id, SUM(total) as total_spent
  FROM orders GROUP BY user_id
)
SELECT * FROM users u
JOIN order_totals ot ON u.id = ot.user_id;

-- Subquery (harder to read)
SELECT * FROM users u
JOIN (
  SELECT user_id, SUM(total) as total_spent
  FROM orders GROUP BY user_id
) ot ON u.id = ot.user_id;