You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/en/guides/54-query/00-cte.md
+93-1Lines changed: 93 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -3,7 +3,7 @@ title: Common Table Expressions (CTEs)
3
3
---
4
4
import FunctionDescription from '@site/src/components/FunctionDescription';
5
5
6
-
<FunctionDescriptiondescription="Introduced or updated: v1.2.429"/>
6
+
<FunctionDescriptiondescription="Introduced or updated: v1.2.530"/>
7
7
8
8
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.
| 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. |
102
102
| MATERIALIZED |`Materialized` is an optional keyword used to indicate whether the CTE should be materialized. |
103
103
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.
|`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
+
104
138
## Usage Examples
105
139
140
+
### Non-Recursive CTEs
141
+
106
142
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.
107
143
108
144
```sql
@@ -227,4 +263,60 @@ WITH stores_with_sales AS (
227
263
)
228
264
DELETEFROM store_details
229
265
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
+
CREATETABLEEmployees (
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
0 commit comments