【问题标题】:detect cycles in a graph in SQL using recursive common table expression使用递归公用表表达式检测 SQL 图中的循环
【发布时间】:2019-11-04 04:23:15
【问题描述】:

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

【问题讨论】:

  • 您还没有在这里提问。你在问什么?
  • 您在寻找什么结果集?样本数据和所需结果的帮助。
  • 输入是名为#myEdge 的表,表示图形数据,@rootNode。输出是显示循环的结果集

标签: sql sql-server recursion


【解决方案1】:
CREATE TABLE #myEdge (
    ID INT IDENTITY(1,1) PRIMARY KEY,
    NodeIDFrom INT,
    NodeIDTo INT
)

INSERT INTO #myEdge(NodeIDFrom, NodeIDTo) VALUES (4, 5),(5, 6),(6, 4);

DECLARE @rootNode AS integer = 4;

--compute the transitive closure from this root. column Niveau holds the recursion nesting level.

WITH cte_transitive_closure(rootNode, NodeFrom, NodeTo, Niveau)
AS (
    SELECT @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
)
SELECT *
INTO #transitive_closure
FROM cte_transitive_closure;

SELECT * FROM #transitive_closure;

--starting from root as a reached target, move back in the trace until the root is hit again.

WITH 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;


result set:

NodeFrom    -> NodeTo   (Cycle)

4   -> NULL (0)

4   -> 5    (1)

5   -> 6    (0)

6   -> 4    (0)

【讨论】:

  • 请用这个查询更新原始问题
猜你喜欢
  • 2011-10-05
  • 1970-01-01
  • 2012-09-15
  • 1970-01-01
  • 1970-01-01
  • 2015-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多