回答

收藏

防止多次递归CTE访问节点

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

考虑以下简单的内容DAG:$ n( k! z$ z/ D: i+ D
        1->2->3->4bar描述表(我在用)SQL Server 2005):parent_id   child_id                          ... other edges,not connected to the subgraph above现在想象一下,我还有其他选择第一个和最后一个边缘的标准,即1-> 2和3-> 4。我想用这些来找到图表的其余部分。$ {4 {& x' [8 h  }# C
我可以写递归CTE,如下所示(我用的是MSDN的术语):3 q# d  O, a2 D0 c5 |6 o
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两次选择:, r5 G6 i7 r+ r' C3 @, i/ O
parent_id  child_id                   333                  4           ///22nd appearance!如何防止查询在描述的子图中重复?如果在查询的递归成员部分,我可以引用 到目前为止,递归CTE所有检索到的数据
7 e* J- Q2 V" m这个目的可以通过在递归成员中提供一个谓词来实现。但是,我认为我只能访问递归成员 最后一次迭代    返回的数据。4 f1 G: p6 e2 m" c# V
当有很多这样的重复时,它将无法很好地扩展。有没有办法防止这种不必要的额外交付?( ?& g3 ^( H; s" J* P1 i
请注意,我可以在句子的最后一行使用选择不同来实现所需的结果,但这似乎是 完成    所有(重复)递归 之后    应用,所以我觉得这不是理想的解决方案。+ h$ v, |7 T; J
Edit    -hainstech建议通过添加谓词来消除递归在起始集中明确的路径(即递归)来停止递归where foo.child_idnot in (1,3)。这只对简单的情况有效,因为它很简单-所有重复集合中开始所有重复部分。它不能解决可能不存在的一般情况。例如,考虑将边线1->5 W* K- X' `! h- [" P1 l
4和4-> 5添加到上述集合中。即使使用建议的谓词,边缘4-> 5也会被捕获两次。, l6 g$ O" T/ K; h/ Y# x  V
                                                               
' w; b2 q2 n+ d0 v  |3 \    解决方案:
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则