微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

sql – 多次预防递归CTE访问节点

考虑以下简单的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将被捕获两次,即使是建议的谓词.

原文地址:https://www.jb51.cc/mssql/82165.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐