СОЕДИНИТЕ ПО NOCYCLE, генерирующему миллионы дочерних узлов - PullRequest
1 голос
/ 30 марта 2020

У меня есть база данных, где from_node и to_node являются столбцами. Попытка найти все достижимые узлы от from_node до to_node. Есть циклы. Несколько from_node, использующих connect by nocycle, генерируют миллионы дочерних узлов. Как это можно решить?

SELECT from_node,
       to_node,
       level
FROM PATH
START WITH from_node = input_var
CONNECT BY NOCYCLE PRIOR to_node= from_node;

Ответы [ 2 ]

1 голос
/ 30 марта 2020

Итак, основываясь на вашем описании, я мог бы рассмотреть использование рекурсивного факторинга подзапроса вместо иерархического запроса. Это позволит вам легче избавиться от циклов. Это потому, что NOCYCLE фактически не останавливает циклы, а мешает Oracle заботиться о них. Это выдержка из документации Oracle :

Параметр NOCYCLE указывает Oracle базе данных возвращать строки из запроса, даже если существует CONNECT BY l oop в данных. Используйте этот параметр вместе с псевдостолбцом CONNECT_BY_ISCYCLE, чтобы увидеть, какие строки содержат l oop. Обратитесь к псевдостолбцу CONNECT_BY_ISCYCLE для получения дополнительной информации.

Что-то вроде этого рекурсивного подзапроса может работать лучше для вас:

WITH path_search (from_node, to_node, path_level) AS
(
  SELECT p.from_node, p.to_node, 0 AS PATH_LEVEL
  FROM paths p
  WHERE p.from_node = 'A'
  UNION ALL
  SELECT p.from_node, p.to_node, ps.path_level+1 AS path_level
  FROM path_search ps
  INNER JOIN paths p ON ps.to_node = p.from_node
)
SEARCH DEPTH FIRST BY to_node SET order_col
CYCLE from_node SET is_cycle TO 'Y' DEFAULT 'N'
SELECT ps.from_node, ps.to_node, MIN(ps.path_level) AS MIN_DISTANCE
FROM path_search ps
WHERE is_cycle = 'N'
GROUP BY ps.from_node, ps.to_node
ORDER BY min_distance;

Вот SQLFiddle с этим решением ( Ссылка ).

Это позволит вам остановить рекурсию после обнаружения цикла в заданном пути. Однако, поскольку все еще могут быть дубликаты от и к узлам, поскольку один и тот же сегмент пути может быть найден на разных путях, я добавил группировку, чтобы показать только минимальный уровень, так как это был бы лучший способ добраться до данного узла.

Редактировать: исправлено несколько опечаток в запросе

0 голосов
/ 05 апреля 2020
    Create table temp_path(
    from_node varchar(2),
     to_node varchar(2));

    INSERT INTO temp_path values('A','B');
    INSERT INTO temp_path values('A','C');
    INSERT INTO temp_path values('A','D');
    INSERT INTO temp_path values('A','E');
    INSERT INTO temp_path values('A','F');
    INSERT INTO temp_path values('A','G');
    INSERT INTO temp_path values('A','H');
    INSERT INTO temp_path values('A','I');
    INSERT INTO temp_path values('A','J');


    INSERT INTO temp_path values('B','K');
    INSERT INTO temp_path values('B','L');
    INSERT INTO temp_path values('B','C');
    INSERT INTO temp_path values('B','E');
    INSERT INTO temp_path values('B','M');
    INSERT INTO temp_path values('B','N');
    INSERT INTO temp_path values('B','O');
    INSERT INTO temp_path values('B','J');

    INSERT INTO temp_path values('C','K');
    INSERT INTO temp_path values('C','N');
    INSERT INTO temp_path values('C','J');



    INSERT INTO temp_path values('D','K');
    INSERT INTO temp_path values('D','B');
    INSERT INTO temp_path values('D','L');
    INSERT INTO temp_path values('D','C');
    INSERT INTO temp_path values('D','E');
    INSERT INTO temp_path values('D','F');
    INSERT INTO temp_path values('D','G');
    INSERT INTO temp_path values('D','M');
    INSERT INTO temp_path values('D','P');
    INSERT INTO temp_path values('D','Q');
    INSERT INTO temp_path values('D','N');
    INSERT INTO temp_path values('D','R');
    INSERT INTO temp_path values('D','O');
    INSERT INTO temp_path values('D','J');

    INSERT INTO temp_path values('E','K');
    INSERT INTO temp_path values('E','L');
    INSERT INTO temp_path values('E','S');
    INSERT INTO temp_path values('E','M');
    INSERT INTO temp_path values('E','N');
    INSERT INTO temp_path values('E','O');
    INSERT INTO temp_path values('E','J');

    INSERT INTO temp_path values('F','K');
    INSERT INTO temp_path values('F','B');
    INSERT INTO temp_path values('F','L');
    INSERT INTO temp_path values('F','C');
    INSERT INTO temp_path values('F','G');
    INSERT INTO temp_path values('F','S');
    INSERT INTO temp_path values('F','M');
    INSERT INTO temp_path values('F','N');
    INSERT INTO temp_path values('E','O');
    INSERT INTO temp_path values('E','J');

    INSERT INTO temp_path values('G','K');
    INSERT INTO temp_path values('G','B');
    INSERT INTO temp_path values('G','L');
    INSERT INTO temp_path values('G','E');
    INSERT INTO temp_path values('G','M');
    INSERT INTO temp_path values('G','N');
    INSERT INTO temp_path values('G','O');
    INSERT INTO temp_path values('G','J');

    INSERT INTO temp_path values('H','K');
    INSERT INTO temp_path values('H','B');
    INSERT INTO temp_path values('H','L');
    INSERT INTO temp_path values('H','C');
    INSERT INTO temp_path values('H','D');
    INSERT INTO temp_path values('H','E');
    INSERT INTO temp_path values('H','F');
    INSERT INTO temp_path values('H','G');
    INSERT INTO temp_path values('H','M');
    INSERT INTO temp_path values('H','P');
    INSERT INTO temp_path values('H','Q');
    INSERT INTO temp_path values('H','R');
    INSERT INTO temp_path values('H','O');
    INSERT INTO temp_path values('H','J');
    INSERT INTO temp_path values('I','K');
    INSERT INTO temp_path values('I','B');
    INSERT INTO temp_path values('I','L');
    INSERT INTO temp_path values('I','C');
    INSERT INTO temp_path values('I','D');
    INSERT INTO temp_path values('I','E');
    INSERT INTO temp_path values('I','F');
    INSERT INTO temp_path values('I','G');
    INSERT INTO temp_path values('I','H');
    INSERT INTO temp_path values('I','M');
    INSERT INTO temp_path values('I','P');
    INSERT INTO temp_path values('I','Q');
    INSERT INTO temp_path values('I','N');
    INSERT INTO temp_path values('I','R');
    INSERT INTO temp_path values('I','O');
    INSERT INTO temp_path values('I','J');


    INSERT INTO temp_path values('J','K');
    INSERT INTO temp_path values('J','L');
    INSERT INTO temp_path values('J','N');
    INSERT INTO temp_path values('J','O');

    INSERT INTO temp_path values('K','N');
    INSERT INTO temp_path values('K','J');

            INSERT INTO temp_path values('L','K');
    INSERT INTO temp_path values('L','N');
    INSERT INTO temp_path values('L','J');

    INSERT INTO temp_path values('M','K');
    INSERT INTO temp_path values('M','B');
    INSERT INTO temp_path values('M','L');
    INSERT INTO temp_path values('M','C');
    INSERT INTO temp_path values('M','E');
    INSERT INTO temp_path values('M','F');
    INSERT INTO temp_path values('M','G');
    INSERT INTO temp_path values('M','N');
    INSERT INTO temp_path values('M','O');
    INSERT INTO temp_path values('M','J');
    INSERT INTO temp_path values('M','F');

    INSERT INTO temp_path values('N','J');

    INSERT INTO temp_path values('O','K');
    INSERT INTO temp_path values('O','L');
    INSERT INTO temp_path values('O','N');
    INSERT INTO temp_path values('O','J');

    INSERT INTO temp_path values('P','K');
    INSERT INTO temp_path values('P','A');
    INSERT INTO temp_path values('P','B');
    INSERT INTO temp_path values('P','L');
    INSERT INTO temp_path values('P','T');
    INSERT INTO temp_path values('P','C');
    INSERT INTO temp_path values('P','D');
    INSERT INTO temp_path values('P','E');
    INSERT INTO temp_path values('P','F');
    INSERT INTO temp_path values('P','G');
    INSERT INTO temp_path values('P','H');
    INSERT INTO temp_path values('P','I');
    INSERT INTO temp_path values('P','N');
    INSERT INTO temp_path values('P','R');
    INSERT INTO temp_path values('P','O');
    INSERT INTO temp_path values('P','J');

    INSERT INTO temp_path values('Q','H');
    INSERT INTO temp_path values('Q','I');
    INSERT INTO temp_path values('Q','D');
    INSERT INTO temp_path values('Q','E');
    INSERT INTO temp_path values('Q','F');
    INSERT INTO temp_path values('Q','G');
    INSERT INTO temp_path values('Q','N');
    INSERT INTO temp_path values('Q','L');
    INSERT INTO temp_path values('Q','K');
    INSERT INTO temp_path values('Q','R');
    INSERT INTO temp_path values('Q','T');
    INSERT INTO temp_path values('Q','A');
    INSERT INTO temp_path values('Q','C');
    INSERT INTO temp_path values('Q','B');
    INSERT INTO temp_path values('Q','O');
    INSERT INTO temp_path values('Q','J');


    INSERT INTO temp_path values('R','K');
    INSERT INTO temp_path values('R','B');
    INSERT INTO temp_path values('R','L');
    INSERT INTO temp_path values('R','C');
    INSERT INTO temp_path values('R','G');
    INSERT INTO temp_path values('R','M');
    INSERT INTO temp_path values('R','N');
    INSERT INTO temp_path values('R','O');
    INSERT INTO temp_path values('R','J');

    INSERT INTO temp_path values('S','K');
    INSERT INTO temp_path values('S','B');
    INSERT INTO temp_path values('S','L');
    INSERT INTO temp_path values('S','C');
    INSERT INTO temp_path values('S','E');
    INSERT INTO temp_path values('S','F');
    INSERT INTO temp_path values('S','G');
    INSERT INTO temp_path values('S','N');
    INSERT INTO temp_path values('S','O');
    INSERT INTO temp_path values('S','J');

    INSERT INTO temp_path values('T','K');
    INSERT INTO temp_path values('T','A');
    INSERT INTO temp_path values('T','B');
    INSERT INTO temp_path values('T','L');
    INSERT INTO temp_path values('T','C');
    INSERT INTO temp_path values('T','D');
    INSERT INTO temp_path values('T','E');
    INSERT INTO temp_path values('T','F');
    INSERT INTO temp_path values('T','G');
    INSERT INTO temp_path values('T','H');
    INSERT INTO temp_path values('T','I');
    INSERT INTO temp_path values('T','M');
    INSERT INTO temp_path values('T','P');
    INSERT INTO temp_path values('T','Q');
    INSERT INTO temp_path values('T','R');
    INSERT INTO temp_path values('T','O');
    INSERT INTO temp_path values('T','J');
...