回答

收藏

防止多次递归CTE访问节点

技术问答 技术问答 186 人阅读 | 0 人回复 | 2023-09-13

考虑以下简单的内容DAG:
: H! z: S% l* l  g0 M/ I        1->2->3->4bar描述表(我在用)SQL Server 2005):parent_id   child_id                          ... other edges,not connected to the subgraph above现在想象一下,我还有其他选择第一个和最后一个边缘的标准,即1-> 2和3-> 4。我想用这些来找到图表的其余部分。
8 m5 c, q* N7 N. a& r' G我可以写递归CTE,如下所示(我用的是MSDN的术语):: a; b  ?+ J9 @1 x, r/ Q
with foo(parent_id,child_id) as (// anchor member that happens to select first and last edges:select parent_id,child_id from #bar where parent_id in (1,3)union all// recursive member:select #bar.* from #barjoin foo on #bar.parent_id = foo.child_id)select parent_id,child_id from foo但这导致边缘3-> 4两次选择:" R/ s6 F  E# W
parent_id  child_id                   333                  4           ///22nd appearance!如何防止查询在描述的子图中重复?如果在查询的递归成员部分,我可以引用 到目前为止,递归CTE所有检索到的数据: E. d$ B/ u/ r" d8 H
这个目的可以通过在递归成员中提供一个谓词来实现。但是,我认为我只能访问递归成员 最后一次迭代    返回的数据。
$ D9 t9 L0 I& g' ^  d& b# ?当有很多这样的重复时,它将无法很好地扩展。有没有办法防止这种不必要的额外交付?
2 a" C8 A$ Z5 R: F7 t6 U; V9 |请注意,我可以在句子的最后一行使用选择不同来实现所需的结果,但这似乎是 完成    所有(重复)递归 之后    应用,所以我觉得这不是理想的解决方案。- T/ J: n) t- m# p! P8 F
Edit    -hainstech建议通过添加谓词来消除递归在起始集中明确的路径(即递归)来停止递归where foo.child_idnot in (1,3)。这只对简单的情况有效,因为它很简单-所有重复集合中开始所有重复部分。它不能解决可能不存在的一般情况。例如,考虑将边线1->7 t( T- w/ k7 g# o2 G/ }5 H3 p
4和4-> 5添加到上述集合中。即使使用建议的谓词,边缘4-> 5也会被捕获两次。# b8 ?" H1 |: m' |# `" v" [6 V
                                                                5 h5 j; a" d' I2 q4 q# y: V
    解决方案:
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则