SQL · Queries that survive scale
How does a recursive CTE work?
Short answer
A recursive CTE has an anchor query and a recursive part joined to the previous result. It repeats until no new rows are produced, which suits trees, graphs, and bill-of-materials.
The anchor query produces the starting rows. The recursive member references the CTE and adds rows based on the previous iteration. UNION ALL is common; UNION removes duplicates but adds cost. Execution stops when the recursive member returns no rows.
WITH RECURSIVE org AS (
SELECT id, name, manager_id, 1 AS depth
FROM employees
WHERE manager_id IS NULL
UNION ALL
SELECT e.id, e.name, e.manager_id, org.depth + 1
FROM employees e
JOIN org ON e.manager_id = org.id
WHERE org.depth < 10
)
SELECT id, name, depth
FROM org
ORDER BY depth, name;Risks and controls
- Cyclic data can loop forever without a depth limit or visited-path check
- Each iteration reads the previous working set, so wide fan-out grows quickly
- Index the join column, here manager_id, to keep each step efficient
- UNION can remove duplicates but requires comparison work on every iteration
- PostgreSQL supports CYCLE detection; other engines need an explicit path column
For a safe cycle check, carry an array or string path and reject rows whose next id is already present. A depth cap is simpler but can truncate valid deep hierarchies, so choose based on the domain.
Follow-ups you should expect
Interviewers use these to check whether the first answer was understanding or memorisation.
- 1What happens if the data contains a cycle?
- 2How do you limit recursion depth?
- 3Why is UNION ALL commonly used in the recursive member?
- 4How would you find all descendants of one node?
Say it in the interview
A recursive CTE starts with an anchor query that selects the base rows. The recursive part joins the table back to the CTE and produces the next level, repeating until no rows remain. I use it for org charts, category trees, and dependency graphs. I always add a cycle guard or depth limit, and I make sure the join column is indexed because each iteration depends on it.
Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.
Related questions
Reading is step one
Now say it out loud.
Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live SQL mock interview and get scored feedback on depth, clarity and confidence.