关于SQL递归CTE执行逻辑的理解是否准确?
递归CTE执行逻辑理解验证
原递归CTE代码及执行结果:
WITH RECURSIVE example (loc, a,b,c) AS ( SELECT 'anchor', 1,2,3 UNION ALL SELECT 'recursive', a*a, b*b, c*c FROM example WHERE c < 50 ) SELECT * FROM example;
执行结果:
┌───────────┬───┬─────┬──────┐ │ loc ┆ a ┆ b ┆ c │ ╞═══════════╪═══╪═════╪══════╡ │ anchor ┆ 1 ┆ 2 ┆ 3 │ │ recursive ┆ 1 ┆ 4 ┆ 9 │ │ recursive ┆ 1 ┆ 16 ┆ 81 │ └───────────┴───┴─────┴──────┘
你对该example递归CTE的构建过程理解如下,现验证其准确性:
- 首先执行锚点SELECT语句,得到初始结果集:
SELECT 'anchor', 1, 2, 3
结果:
┌───────────┬───┬─────┬──────┐ │ loc ┆ a ┆ b ┆ c │ ╞═══════════╪═══╪═════╪══════╡ │ anchor ┆ 1 ┆ 2 ┆ 3 │ └───────────┴───┴─────┴──────┘
- 接着执行递归部分,首次递归基于初始行执行,得到第一条递归结果:
SELECT 'recursive', a*a, b*b, c*c FROM (VALUES ('anchor', 1,2,3)) AS example (loc,a,b,c) WHERE c < 50
结果:
┌───────────┬───┬─────┬──────┐ │ loc ┆ a ┆ b ┆ c │ ╞═══════════╪═══╪═════╪══════╡ │ recursive ┆ 1 ┆ 4 ┆ 9 │ └───────────┴───┴─────┴──────┘
- 再次以上一次迭代的结果为输入,执行递归语句得到第二条递归结果:
SELECT 'recursive', a*a, b*b, c*c FROM (VALUES ('recursive', 1,4,9)) AS example (loc,a,b,c) WHERE c < 50
结果:
┌───────────┬───┬─────┬──────┐ │ loc ┆ a ┆ b ┆ c │ ╞═══════════╪═══╪═════╪══════╡ │ recursive ┆ 1 ┆ 16 ┆ 81 │ └───────────┴───┴─────┴──────┘
- 继续迭代时,因c值不满足条件返回空结果集,递归终止:
SELECT 'recursive', a*a, b*b, c*c FROM (VALUES ('recursive', 1,16,81)) AS example (loc,a,b,c) WHERE c < 50
结果:[empty]
你将递归CTE展开为多次UNION ALL的形式如下:
WITH example (loc, a,b,c) AS ( SELECT 'anchor', 1, 2, 3 UNION ALL SELECT 'recursive', a*a, b*b, c*c FROM (VALUES ('anchor',1,2,3)) example (loc,a,b,c) WHERE c < 50 UNION ALL SELECT 'recursive', a*a, b*b, c*c FROM (VALUES ('recursive', 1,4,9)) example (loc,a,b,c) WHERE c < 50 UNION ALL SELECT 'recursive', a*a, b*b, c*c FROM (VALUES ('recursive', 1,16,81)) example (loc,a,b,c) WHERE c < 50 ) SELECT * FROM example
执行结果:
┌───────────┬───┬────┬────┐ │ loc ┆ a ┆ b ┆ c │ ╞═══════════╪═══╪════╪════╡ │ anchor ┆ 1 ┆ 2 ┆ 3 │ │ recursive ┆ 1 ┆ 4 ┆ 9 │ │ recursive ┆ 1 ┆ 16 ┆ 81 │ └───────────┴───┴────┴────┘
你的理解完全准确。递归CTE的核心执行逻辑就是:
- 先执行锚点查询生成初始结果集;
- 之后每一轮递归都以上一轮迭代输出的结果集作为递归查询的输入,生成新的结果;
- 当递归查询返回空结果集时,达到不动点,递归终止;
- 最终将锚点结果与所有递归迭代产生的有效结果合并后返回。
内容的提问来源于stack exchange,提问作者David542
相关产品推荐
相关产品推荐

