A recursive common table expression is a powerful SQL construct that allows you to perform complex data manipulation and retrieval. It is particularly useful for working with hierarchical or tree-structured data.
With recursive CTE, the query can refer to its own output.
The basis: CTE (non recursive)
WITH my_cte AS (
SELECT column1, column2
FROM my_table
)
SELECT *
FROM my_cte;
The WITH clause allows the creation of auxiliary statements, to be used within a larger query.
These CTEs essentially define temporary tables that are only valid for the duration of a single query.
The WITH clause can contain one or more auxiliary statements, which can be a SELECT, INSERT, UPDATE, or DELETE statement.
The WITH clause is then attached to a primary statement, which can also be a SELECT, INSERT, UPDATE, or DELETE statement.
CTE recursive – Template
WITH RECURSIVE expression_name (column_list)
AS
(
-- Anchor member
initial query
UNION ALL
-- Recursive member
recursive query
)
SELECT *
FROM expression_name
A recursive CTE consists of two parts:
- An anchor member:
The base result set of the CTE - A recursive member:
References the CTE itself and builds upon the result set of the anchor member.
The recursive member is executed repeatedly until it returns an empty result set. At each iteration, the result set of the previous iteration is used as input for the next iteration.
Basic example
The sum of the first 10 numbers:
WITH RECURSIVE nb (n) AS (
VALUES (1)
UNION
SELECT n+1 FROM nb WHERE n < 10
)
SELECT sum(n) FROM nb;
Explanations:
- nb : CTE name
- VALUES (1)
The base result set, contains only the value 1. - SELECT n+1 FROM nb WHERE n < 10
The recursive query, which references the CTE itself.
At the first iteration, the result set contains the values 1 and 2.
At the second iteration, the result set contains the values 1, 2 and 3.
…
More complex example
We have a “relationship” table which contains the relationship parent / child.
Get all ancestors of “andré”:
WITH RECURSIVE descent (child) AS (
select child from relationship where parent = 'andré'
UNION
SELECT relationship.child FROM descent join relationship on descent.child = relationship.parent
)
SELECT * FROM descent;
Explanations:
- select child from relationship where parent = ‘andré’:
Select André’s children - SELECT relationship.child FROM descent join relationship on descent.child = relationship.parent
Recursively selects the children of the selection.
You can use our MySQL sandbox to test yourself: Mysql Playground.
Conclusion
Recursive CTEs are quite easy to write, yet they can yield powerful queries. They allow you to avoid having to write recursive code that executes multiple SQL queries, instead of just writing a simple, readable SQL query.
Leave a Reply