Recursive CTEs in PostgreSQL

From the PostgreSQL Advanced Features cheat sheet · CTEs & Advanced Queries · verified Jul 2026

Recursive CTEs

Process hierarchical and graph data

sql
-- Organizational hierarchy
WITH RECURSIVE org_chart AS (
  -- Anchor: start with CEO
  SELECT id, name, manager_id, 0 as level
  FROM employees
  WHERE manager_id IS NULL
  
  UNION ALL
  
  -- Recursive: find subordinates
  SELECT e.id, e.name, e.manager_id, oc.level + 1
  FROM employees e
  JOIN org_chart oc ON e.manager_id = oc.id
)
SELECT * FROM org_chart
ORDER BY level, name;

-- DETAILED_TAB:
-- Generate series with recursive CTE
WITH RECURSIVE dates AS (
  SELECT DATE '2024-01-01' as date
  UNION ALL
  SELECT (date + INTERVAL '1 day')::date
  FROM dates
  WHERE date < '2024-01-31'
)
SELECT date FROM dates;

-- Find all related records (graph traversal)
WITH RECURSIVE related AS (
  -- Start node
  SELECT id, parent_id, name, ARRAY[id] as path
  FROM categories
  WHERE id = 5
  
  UNION ALL
  
  -- Find connections
  SELECT c.id, c.parent_id, c.name, r.path || c.id
  FROM categories c
  JOIN related r ON c.parent_id = r.id
  WHERE NOT c.id = ANY(r.path)  -- Avoid cycles
)
SELECT * FROM related;
🔴 Advanced - Powerful but can be complex
💡 Always have a termination condition
⚠️ Watch for infinite loops - use path tracking
📌 Great for trees, graphs, and hierarchies
⚡ Consider ltree extension for hierarchies
recursivectehierarchy

More PostgreSQL tasks

Back to the full PostgreSQL Advanced Features cheat sheet