Find all nodes in an adjacency list model with oracle connect by

霸气de小男生 提交于 2019-12-03 21:38:52
APC

Oracle's CONNECT BY syntax is intended for traversing hierarchical data: it is uni-directional so not a suitable for representing a graph, which requires bi-directionality. There's no way to go 2 -> 1 -> 3 in one query, which is what you need to do to get all the nodes starting from 5.


A long timne ago I answered a question on flattening nodes in a hierarchy (AKA transitive closure) i.e. if 1->2->3 is true, `1->3' is true as well. It links to a paper which demonstrates a PL/SQL solution to generate all the edges and store them in a table. A similar solution could be used in this case. But obviously it is only practical if the nodes in the graph don't chnage very often. So perhaps it will only be of limited use. Anyway, find out more.

Finally I came up with a solution similar like this:

  SELECT child FROM child_parent START WITH parent =
   (
    SELECT DISTINCT parent FROM   
     (
      SELECT parent
      FROM child_parent
      WHERE CONNECT_BY_ISLEAF = 1
        START WITH child = 5
        CONNECT BY PRIOR parent = child
      UNION
      SELECT parent
      FROM child_parent
      WHERE parent = 5
     ) 
   )
   CONNECT BY NOCYCLE PRIOR child = parent
   UNION
   SELECT DISTINCT parent FROM   
   (
    SELECT parent
    FROM child_parent
    WHERE CONNECT_BY_ISLEAF = 1
      START WITH child = 5
      CONNECT BY PRIOR parent = child
    UNION
    SELECT parent
    FROM child_parent
    WHERE parent = 5
   );

It works with all nodes for the provided example. But if one of the leafs has a second parent and the starting point is above this node or in a different branch it don't work.

But for me it is good enough.

A solution to get all nodes in graph could be: implement the opposite of the query above (from top to bottom) and then execute them (bottom to top, top to bottom) vice versa until you find no more new nodes. This would need PL/SQL and I also don't know about the performance.

Using 5 you cannot traverse whole tree and it's going to very very tricky even if you can achieve it as it is a leaf element.

Try below query, it will traverse whole tree but you will have to start from root instead of leaf:

select * from (
SELECT child FROM child_parent START WITH  parent = 1 
              CONNECT BY NOCYCLE PRIOR child = parent
union
select 1 from dual)
order by child;

you can replace "1" with any other root element, all elements below that root will be printed including that root.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!