考虑以下简单的DAG:
1->2->3->4
和一个表,#bar,描述这个(我使用sql Server 2005):
parent_id child_id 1 2 2 3 3 4 //... other edges,not connected to the subgraph above
现在想象我有一些其他任意的选择第一个和最后一个边的标准,即1> 2和3> 4.我想用这些来找到我的图表的其余部分.
我可以写一个递归的CTE如下(我使用的术语从MSDN):
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 #bar join foo on #bar.parent_id = foo.child_id ) select parent_id,child_id from foo
然而,这导致边缘3→4被选择两次:
parent_id child_id 1 2 3 4 2 3 3 4 // 2nd appearance!
如何阻止查询递归到已经描述的子图中?我可以实现这一点,如果在我的“递归成员”部分的查询中,我可以引用所有已经被递归CTE检索的所有数据到目前为止(并且提供一个在递归成员中指示的排除已访问节点的谓词).但是,我想我可以只访问递归成员的最后一次迭代返回的数据.
当有这么多重复时,这不会很好.有没有办法防止这种不必要的附加递归?
请注意,我可以在我的语句的最后一行使用“select distinct”来实现所需的结果,但这似乎在所有的(重复的)递归完成之后被应用,所以我不认为这是一个理想的解决方案.
编辑 – hainstech建议停止递归,通过添加一个谓词来排除明确在起始集中的递归路径,即仅在(1,3)中的foo.child_id不在的地方递归.这仅适用于上述情况,因为它很简单 – 所有重复的部分都在锚节点内开始.它不能解决他们可能不是的一般情况.例如,考虑将边缘1→4和4> 5添加到上述集合.边缘4> 5将被捕获两次,即使是建议的谓词.