Recursive queries allow SQL databases to process hierarchical or tree-structured data, such as organizational charts, category trees, and ancestry relationships. They are implemented using Common Table Expressions (CTEs) with the WITH RECURSIVE clause.
This tutorial covers the fundamentals of recursive queries, their syntax, and practical examples.
Recursive queries are useful when working with:
Instead of performing multiple self-joins, recursive queries efficiently retrieve multi-level hierarchical data in a single execution.
A recursive CTE consists of two parts:
WITH RECURSIVE cte_name AS (
-- Anchor Query (Base Case)
SELECT column1, column2 FROM table WHERE condition
UNION ALL
-- Recursive Query (Recursive Case)
SELECT column1, column2 FROM table, cte_name WHERE join_condition
)
SELECT * FROM cte_name;The recursive query repeatedly executes until no more rows are returned.
Consider an employees table where each employee has a manager_id.
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(100),
manager_id INT
);| id | name | manager_id |
|---|---|---|
| 1 | Alice | NULL |
| 2 | Bob | 1 |
| 3 | Charlie | 1 |
| 4 | David | 2 |
| 5 | Eve | 2 |
| 6 | Frank | 3 |
WITH RECURSIVE EmployeeHierarchy AS (
-- Anchor Query: Get the top-level manager (Alice)
SELECT id, name, manager_id, 1 AS hierarchy_level
FROM employees
WHERE manager_id IS NULL
UNION ALL
-- Recursive Query: Get employees reporting to previous level
SELECT e.id, e.name, e.manager_id, eh.hierarchy_level + 1
FROM employees e
INNER JOIN EmployeeHierarchy eh ON e.manager_id = eh.id
)
SELECT * FROM EmployeeHierarchy;| id | name | manager_id | hierarchy_level |
|---|---|---|---|
| 1 | Alice | NULL | 1 |
| 2 | Bob | 1 | 2 |
| 3 | Charlie | 1 | 2 |
| 4 | David | 2 | 3 |
| 5 | Eve | 2 | 3 |
| 6 | Frank | 3 | 3 |
Explanation:
Consider a categories table for an e-commerce website.
CREATE TABLE categories (
id INT PRIMARY KEY,
category_name VARCHAR(100),
parent_id INT
);| id | category_name | parent_id |
|---|---|---|
| 1 | Electronics | NULL |
| 2 | Phones | 1 |
| 3 | Laptops | 1 |
| 4 | Android | 2 |
| 5 | iPhone | 2 |
| 6 | Gaming Laptops | 3 |
WITH RECURSIVE CategoryTree AS (
-- Anchor Query: Fetch top-level categories
SELECT id, category_name, parent_id, 1 AS level
FROM categories
WHERE parent_id IS NULL
UNION ALL
-- Recursive Query: Get subcategories
SELECT c.id, c.category_name, c.parent_id, ct.level + 1
FROM categories c
INNER JOIN CategoryTree ct ON c.parent_id = ct.id
)
SELECT * FROM CategoryTree ORDER BY level;| id | category_name | parent_id | level |
|---|---|---|---|
| 1 | Electronics | NULL | 1 |
| 2 | Phones | 1 | 2 |
| 3 | Laptops | 1 | 2 |
| 4 | Android | 2 | 3 |
| 5 | iPhone | 2 | 3 |
| 6 | Gaming Laptops | 3 | 3 |
Explanation:
Recursive queries can be slow if the hierarchy is too deep. To optimize:
id and parent_id columns.OPTION (MAXRECURSION n) (SQL Server).WITH RECURSIVE CTEs allow self-referencing queries in SQL.Understanding and optimizing recursive queries can greatly enhance database performance when handling hierarchical data.
Sign in to join the discussion and post comments.
Sign in