Common Table Expressions (CTEs) are a powerful SQL feature that create temporary named result sets within a query. When combined with recursion, they become especially useful for working with hierarchical data like organizational charts, family trees, or category structures.
A recursive CTE consists of two main parts: a base case (anchor) and a recursive case. The base case defines the starting point of the recursion - typically the root nodes in your hierarchy. The recursive case defines how to traverse from one level to the next by joining the CTE to itself.
The general pattern follows this structure:
WITH RECURSIVE cte_name AS ( -- Base case: starting points SELECT columns FROM table WHERE condition UNION ALL -- Recursive case: join to build next level SELECT columns FROM table t JOIN cte_name c ON t.parent_id = c.id )
Recursive CTEs are particularly valuable for flattening tree structures into tabular results. Instead of making multiple queries or complex application logic to traverse a hierarchy, a single recursive CTE can efficiently build the complete tree in one operation. They can calculate depths, build paths, aggregate values up or down the hierarchy, and handle complex organizational relationships.
The recursion automatically terminates when no new rows are found in the recursive step, making it safe for well-formed hierarchical data. Most databases also provide safeguards against infinite recursion through maximum recursion depth limits.
1WITH RECURSIVE category_tree AS (
2 -- Base case: top-level categories
3 SELECT id, name, parent_id, 0 as depth, name as path
4 FROM categories
5 WHERE parent_id IS NULL
6
7 UNION ALL
8
9 -- Recursive case: child categories
10 SELECT c.id, c.name, c.parent_id, ct.depth + 1,
11 ct.path || ' > ' || c.name as path
12 FROM categories c
13 JOIN category_tree ct ON c.parent_id = ct.id
14)
15SELECT * FROM category_tree ORDER BY path;