使用递归公用表表达式在SQL中检测图的周期

时间:2019-06-21 10:13:10

标签: sql sql-server recursion

给定一个具有循环的有向图,如何仅使用标准SQL检测并列出循环? 输入=图形边缘和一个根节点,我们从中计算传递闭包。输出=循环中的节点列表。

1 个答案:

答案 0 :(得分:0)

创建表#myEdge(     ID INT IDENTITY(1,1)主键,     NodeIDFrom INT,     NodeIDTo INT )

插入#myEdge(NodeIDFrom,NodeIDTo)值(4,5),(5,6),(6,4);

DECLARE @rootNode AS整数= 4;

-从此根计算传递闭包。 Niveau列保留递归嵌套级别。

与cte_transitive_closure(rootNode,NodeFrom,NodeTo,Niveau) AS(     选择@ rootNode,NULL,@ rootNode,0

UNION ALL

SELECT rootNode, e.NodeIDFrom, e.NodeIDTo, Niveau+1
FROM cte_transitive_closure AS cte
JOIN #myEdge AS e ON cte.NodeTo=e.NodeIdFrom
WHERE Niveau < 99

) 选择 * INTO #transitive_closure FROM cte_transitive_closure;

SELECT * FROM #transitive_closure;

-从根开始作为已达到的目标,在跟踪中移回直到再次击中根。

与cte_cycle(NodeFrom,NodeTo,Cycle) AS(     SELECT @ rootNode,NULL,0

UNION ALL

SELECT t.NodeFrom, t.NodeTo, 0
FROM cte_cycle AS cte
JOIN #transitive_closure AS t ON cte.NodeFrom = t.NodeTo
WHERE t.NodeFrom != @rootNode AND Cycle=0

UNION ALL

SELECT t.NodeFrom, t.NodeTo, 1
FROM cte_cycle AS cte
JOIN #transitive_closure AS t ON cte.NodeFrom = t.NodeTo
WHERE t.NodeFrom = @rootNode AND Cycle=0

) SELECT DISTINCT * FROM cte_cycle;

结果集:

NodeFrom-> NodeTo(循环)

4-> NULL(0)

4-> 5(1)

5-> 6(0)

6-> 4(0)