在介绍recursive common table expression之前,我们先来认识一下什么是common table expression。
Common Table Expressions
在MySQL :: MySQL 8.0 Reference Manual :: 13.2.15 WITH (Common Table Expressions)中,它对common table expression (CTE)的解释如下:
A common table expression (CTE) is a named temporary result set that exists within the scope of a single statement and that can be referred to later within that statement, possibly multiple times.
一个common table expression (CTE)是一个拥有名称的临时结果集,它存在于一条语句的范围之内,它之后能被那条语句引用。
我们先看一个例子:
WITH cte (col1, col2) AS
(
SELECT 1, 2
)
SELECT col1, col2 FROM cte;
上面的例子中,你使用with子句定义了一个名叫cte的CTE,它拥有(col1, col2)
两列,它只拥有(1, 2)
这一行数据。之后的SELECT
语句就能够使用这个CTE了。执行上述语句的结果如下:
+------+------+
| col1 | col2 |
+------+------+
| 1 | 2 |
+------+------+
Recursive Common Table Expressions
介绍完CTE后,我们来看看recursive CTE是怎样的。
recursive CTE的子查询包含两部分,通过UNION [ALL]
或者UNION DISTINCT
分割。就像下面一样:
SELECT ... -- return initial row set
UNION ALL
SELECT ... -- return additional row sets
第一个SELECT
为CTE产生初始行集,并且不会引用CTE的名称。第二个SELECT
产生额外的行集,并且通过在它的FROM子句中引用CTE的名称递归,当不再产生新的行时,递归中止。递归的每次迭代只操作上一次迭代所产生的行。
让我们来看一个例子来更好地理解。
WITH RECURSIVE cte (n) AS
(
SELECT 1
UNION ALL
SELECT n + 1 FROM cte WHERE n < 5
)
SELECT * FROM cte;
# 执行结果如下:
+------+
| n |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+------+
我们来分析一下为什么会得到这样的结果。首先SELECT 1
会产生初始化行集,此时,cte
所代表的结果集只有一行数据。接下来会开始第二个SELECT
的递归。第一次迭代会操作初始化行集(1)
并产生(2)
,第二次迭代会第一次迭代产生的行集(2)
并产生(3)
,一直这样下去,知道递归中止,也就是n
不再小于5
时。
这里其实只是简单的介绍了CTE和recursive CTE,想了解更多的话还是建议去查看官方文档。