Skip to content

Commit dc82f74

Browse files
authored
docs: recursive cte (#850)
* Update 00-cte.md * Update 00-cte.md
1 parent 14b6a54 commit dc82f74

File tree

1 file changed

+93
-1
lines changed

1 file changed

+93
-1
lines changed

docs/en/guides/54-query/00-cte.md

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: Common Table Expressions (CTEs)
33
---
44
import FunctionDescription from '@site/src/components/FunctionDescription';
55

6-
<FunctionDescription description="Introduced or updated: v1.2.429"/>
6+
<FunctionDescription description="Introduced or updated: v1.2.530"/>
77

88
Databend supports common table expressions (CTEs) with a WITH clause, allowing you to define one or multiple named temporary result sets used by the following query. The term "temporary" implies that the result sets are not permanently stored in the database schema. They act as temporary views only accessible to the following query.
99

@@ -101,8 +101,44 @@ SELECT ... | UPDATE ... | DELETE FROM ...
101101
| cte_column_list | The names of the columns in the CTE. A CTE can refer to any CTEs in the same WITH clause that are defined before. |
102102
| MATERIALIZED | `Materialized` is an optional keyword used to indicate whether the CTE should be materialized. |
103103

104+
## Recursive CTEs
105+
106+
A recursive CTE is a temporary result set that references itself to perform recursive operations, allowing the processing of hierarchical or recursive data structures.
107+
108+
### Syntax
109+
110+
```sql
111+
WITH RECURSIVE <cte_name> AS (
112+
<initial_query>
113+
UNION ALL
114+
<recursive_query> )
115+
SELECT ...
116+
```
117+
118+
| Parameter | Description |
119+
|-------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
120+
| `cte_name` | The CTE name. |
121+
| `initial_query` | The initial query that is executed once at the start of the recursion. It typically returns a set of rows. |
122+
| `recursive_query` | The query that references the CTE itself and is executed repeatedly until an empty result set is returned. It must include a reference to the CTE's name. The query must NOT include aggregate functions (e.g., MAX, MIN, SUM, AVG, COUNT), window functions, GROUP BY clause, ORDER BY clause, LIMIT clause, or DISTINCT. |
123+
124+
### How it Works
125+
126+
The following describes the detailed execution order of a recursive CTE:
127+
128+
1. **Initial Query Execution**: This query forms the base result set, denoted as R0. This result set provides the starting point for the recursion.
129+
130+
2. **Recursive Query Execution**: This query uses the result set from the previous iteration (starting with R0) as input and produces a new result set (Ri+1).
131+
132+
3. **Iteration and Combination**: The recursive execution continues iteratively. Each new result set (Ri) from the recursive query becomes the input for the next iteration. This process repeats until the recursive query returns an empty result set, indicating that the termination condition has been met.
133+
134+
4. **Final Result Set Formation**: Using the `UNION ALL` operator, the result sets from each iteration (R0 through Rn) are combined into a single result set. The `UNION ALL` operator ensures that all rows from each result set are included in the final combined result.
135+
136+
5. **Final Selection**: The final `SELECT ...` statement retrieves the combined result set from the CTE. This statement can apply additional filtering, sorting, or other operations on the combined result set to produce the final output.
137+
104138
## Usage Examples
105139

140+
### Non-Recursive CTEs
141+
106142
Imagine you manage several bookstores located in different regions of the GTA area, and use a table to hold their store IDs, regions, and the trading volume for the last month.
107143

108144
```sql
@@ -227,4 +263,60 @@ WITH stores_with_sales AS (
227263
)
228264
DELETE FROM store_details
229265
WHERE storeid NOT IN (SELECT storeid FROM stores_with_sales);
266+
```
267+
268+
### Recursive CTEs
269+
270+
First, we create a table to store employee data, including their ID, name, and manager ID.
271+
272+
```sql
273+
CREATE TABLE Employees (
274+
EmployeeID INT,
275+
EmployeeName VARCHAR(100),
276+
ManagerID INT
277+
);
278+
```
279+
280+
Next, we insert sample data into the table to represent a simple organizational structure.
281+
282+
```sql
283+
INSERT INTO Employees (EmployeeID, EmployeeName, ManagerID) VALUES
284+
(1, 'Alice', NULL), -- Alice is the CEO
285+
(2, 'Bob', 1), -- Bob reports to Alice
286+
(3, 'Charlie', 1), -- Charlie reports to Alice
287+
(4, 'David', 2), -- David reports to Bob
288+
(5, 'Eve', 2), -- Eve reports to Bob
289+
(6, 'Frank', 3); -- Frank reports to Charlie
290+
```
291+
292+
Now, we use a recursive CTE to find the hierarchy of employees under a specific manager, say Alice (EmployeeID = 1).
293+
294+
```sql
295+
WITH RECURSIVE EmployeeHierarchy AS (
296+
-- Initial query: start with the specified manager (Alice)
297+
SELECT EmployeeID, EmployeeName, ManagerID
298+
FROM Employees
299+
WHERE ManagerID IS NULL -- Alice, since she has no manager
300+
UNION ALL
301+
-- Recursive query: find employees reporting to the current level
302+
SELECT e.EmployeeID, e.EmployeeName, e.ManagerID
303+
FROM Employees e
304+
INNER JOIN EmployeeHierarchy eh ON e.ManagerID = eh.EmployeeID
305+
)
306+
SELECT * FROM EmployeeHierarchy;
307+
```
308+
309+
The output will list all employees in the hierarchy under Alice:
310+
311+
```sql
312+
┌──────────────────────────────────────────────────────┐
313+
│ employeeid │ employeename │ managerid │
314+
├─────────────────┼──────────────────┼─────────────────┤
315+
1 │ Alice │ NULL
316+
2 │ Bob │ 1
317+
3 │ Charlie │ 1
318+
4 │ David │ 2
319+
5 │ Eve │ 2
320+
6 │ Frank │ 3
321+
└──────────────────────────────────────────────────────┘
230322
```

0 commit comments

Comments
 (0)