sql - 如何停止 CTE 中的递归?
问题描述
我有一个如下所示的数据库表:
ID | PredecessorID | Data
-------------------------------------|--------------------------------------|-----------------
43b1e103-d8c6-40f9-b031-e5d9ef18a739 | null | ...
55f6951b-5ed3-46c8-9ad5-64e496cb521a | 43b1e103-d8c6-40f9-b031-e5d9ef18a739 | ...
3eaa0889-31a6-449d-a499-e4beb9e4cad1 | 55f6951b-5ed3-46c8-9ad5-64e496cb521a | ...
我知道我可以使用(递归)公用表表达式(CTE)来获取我的数据的排序列表:
WITH cte (ID, Data)
AS
(
-- base case
SELECT x.ID, x.Data
FROM MyTable AS x
WHERE x.PredecessorID IS NULL
UNION ALL
-- other cases
SELECT x.ID, x.Data
FROM MyTable as x
INNER JOIN cte
ON x.PredecessorID = cte.ID
)
SELECT * FROM cte
虽然这可行,但如果我想获取整个表,我想知道如何只获取表的一部分,例如从 IDx
到 ID之间的所有内容y
。
获得正确的下限很容易(我假设):只需WHERE
将基本案例的标准更改为我想要开始的 ID:
-- base case
SELECT x.ID, x.Data
FROM MyTable AS x
WHERE x.PredecessorID='...'
但是上限呢?一旦达到带有 ID 的记录,我如何告诉 CTE 停止递归y
?
解决方案
由于您在此处进行迭代并且在递归术语中获得了 cte 的最后一个 id,因此您可以过滤掉最后一次迭代命中“y”的结果
WITH cte (ID, Data)
AS
(
-- base case
SELECT x.ID, x.Data
FROM MyTable AS x
WHERE x.PredecessorID IS NULL
UNION ALL
-- other cases
SELECT x.ID, x.Data
FROM MyTable as x
INNER JOIN cte
ON x.PredecessorID = cte.ID
WHERE cte.id <> 'y'
)
SELECT * FROM cte;
请注意,如果您的x
id 有许多分支,其中一些不会导致“y”,那么这些分支将继续迭代,直到它们达到自然结束。只有通向的分支y
会在这里提前停止。
推荐阅读
- ios - 使用 unwind segue 返回上一页
- jdbc - 带有 SSL 选项的 Oracle SQL 开发人员中的 DB2 数据库
- vertica - 基于日期差异分组而不使用递归
- javascript - 如何使用 nightwatch 框架清除字段?
- java - 从枚举创建单例豆
- android - Android Studio 无法索引具有庞大项目的 R.xxx 类
- python - 学习正则表达式反向引用,我不明白发生了什么
- ios - 从 AF.Request 响应中获取数据
- git - 如何在给定作者编写的存储库中搜索代码模式?
- javascript - 如何在 PHP 的数组中找到 max()?