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

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 'EastRiver' 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...