本文介绍CTE的功能和命令格式。
功能介绍
CTE(Common Table Expressions)表示公用表表达式,是一个临时命名结果集,用于简化SQL。是一个statement级别的子句表达式,以WITH开头,后跟表达式名称。包括以下两类:
Recursive CTE表示CTE可以迭代访问自身的场景,能够实现SQL的递归查询功能。
Non Recursive CTE表示非递归CTE,即CTE不使用递归,不迭代访问自己。
语法
with_clause:
WITH [RECURSIVE]
cte_name [(col_name [, col_name] ...)] AS (subquery)
[, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...
Recursive CTE
WITH RECURSIVE cte (n) AS
(
SELECT 1
UNION ALL
SELECT n + 1 FROM cte WHERE n < 5
)
SELECT * FROM cte;
Non Recursive CTE
WITH
cte1 AS (SELECT a, b FROM table1),
cte2 AS (SELECT c, d FROM table2)
SELECT b, d FROM cte1 JOIN cte2
WHERE cte1.a = cte2.c;
约束
recursive part不能包含聚合函数、窗口函数、GROUP BY、ORDER BY、DISTINCT;
recursive part中访问CTE自身只能访问一次,并且只能在FROM子句访问,不可以在子查询中访问;
recursive part子句中访问CTE时,CTE不可以在left join的右侧。
说明
Recursive CTE子句必须以WITH RECURSIVE开头,否则会提示报错信息
ERROR 1146 (42S02): Table 'cte_name' doesn't exist
;如果CTE没有指向自己形成迭代,RECURSIVE可以有但无效果;
Recursive CTE包含两部分查询子句,通过UNION ALL或UNION连接:
SELECT ... -- non recursive part, return initial row set UNION [ALL] SELECT ... -- recursive part, return additional row sets
其中第一个查询子句
non recursive part
负责生成初始数据,这个查询子句不能指向CTE自身。第二个查询子句生成附加行,并且会在FROM子句中访问CTE自身。迭代执行会在第二个查询子句recursive part
无法查出新数据时停止;Recursive CTE的返回类型由
non recursive part
决定,并且全部为nullable;每轮迭代时,
recursive part
引用自身的数据仅限上一次迭代产生的数据,而非之前产生的全部数据;变量基于变量名和位置决定在每轮迭代中的赋值:
WITH RECURSIVE cte AS ( SELECT 1 AS n, 1 AS p, -1 AS q UNION ALL SELECT n + 1, q * 2, p * 2 FROM cte WHERE n < 5 ) SELECT * FROM cte;
如上所示,n、p、q变量在
non recursive part
赋值后,在recursive part中基于变量名去做赋值。recursive part
执行完成以后,基于project中的位置对变量赋值。因此以上示例的输出为:+------+------+------+ | n | p | q | +------+------+------+ | 1 | 1 | -1 | | 2 | -2 | 2 | | 3 | 4 | -4 | | 4 | -8 | 8 | | 5 | 16 | -16 | +------+------+------+
通过limit控制recursive次数,即
recursive cte
的union子句后面可以接limit。
参数说明
cte_max_recursion_depth:recursive part子句迭代执行次数的上限,默认值为500。