PostgreSQL
CTEs and WITH RECURSIVE
A categories table with a parent_id column. The task: find all subcategories of "Electronics" at any depth. Without a recursive CTE, this requires N queries in application code, a stored procedure with a loop, or denormalization. One recursive CTE solves it in standard SQL. For graphs with cycles - the same tool with a small addition.
- **Org charts (HR systems):** who reports to manager X at all levels of hierarchy - WITH RECURSIVE in a single query
- **Routing (logistics):** find all possible delivery paths from A to B - graph traversal via CTE
- **Finance (accounts):** transitive closure of account dependencies for detecting circular references
CTEs: Syntax and When to Apply
A **CTE (Common Table Expression)** is a named subquery defined at the top of a query with `WITH`. The CTE result can be referenced multiple times in the main query, as if it were a temporary table. The primary value is readability: a complex query splits into named, sequential steps.
**CTE vs subquery in FROM:** syntactically interchangeable for simple cases. CTE wins when: (1) the same subquery is needed multiple times, (2) the query should be read top-to-bottom as an algorithm, (3) recursion is required.
The main advantage of a CTE over an equivalent subquery in FROM:
Recursive CTEs
With the `RECURSIVE` keyword, a CTE can reference itself. This is the only way in standard SQL to perform iterative computations without procedural code. The structure is always the same: a base case (anchor) plus a recursive step, joined with `UNION ALL`.
**Preventing infinite recursion:** always add a terminating condition in WHERE or use `LIMIT`. For graphs with cycles, track the path via an array of visited nodes. PostgreSQL has no built-in protection against infinite loops in recursive CTEs.