Учитывая ориентированный граф с циклом, как вы обнаруживаете и перечисляете цикл, используя только стандартный SQL? input = ребра графа и корневой узел, из которого мы вычисляем транзитивное замыкание. Выход = список узлов в цикле.
Какой набор результатов вы ищете? Образцы данных и желаемые результаты помогают.
вводом является таблица с именем #myEdge, представляющая данные графика, и @rootNode. Выход - это набор результатов, показывающий цикл
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)
пожалуйста, обновите исходный вопрос с этим запросом
Вы не задали вопрос здесь. Что ты спрашиваешь?