Home > OS >  Hierarchical Query: Parents parent child
Hierarchical Query: Parents parent child

Time:10-26

I was trying to achieve the result as mentioned below using hierarchical queries in Oracle, tried various ways using CONNECT_BY_ROOT, CONNECT BY PRIOR,... but somehow not able to break into the desired result.

CREATE TABLE test (
    id int, 
    name varchar2(75),
    parentid int, 
    class int
    );


INSERT into test values (1,   'BOSS',null,null);
INSERT into test values (2,   'C1',1, 0);
INSERT into test values (34,  'C2',2, 1);
INSERT into test values (37,  'C3',34, 2);
INSERT into test values (50,  'C4',37, 2);
INSERT into test values (51,  'C5',50, 4);
INSERT into test values (100, 'C6',37, 4);
INSERT into test values (101, 'C7',37, 5);

In a query, if I pass 'C4's id=50 and class=4, then it should return its child i.e. C5 (whose parentid is 50) at the same time it should also fetch C6 (because this is C4's parent's child i.e. C4's parent is C3 and it got a child C6 i.e. parentid 37)

51  C5  50  -- This is Child of C4 i.e. C5's parent=50 
100 C6  37  -- This is because C4 parent is C3 and in turn C3 has another child C6 of same class 

I started with some basic query and did some changes to fetch the desired result but no success...I know this is not correct...and missing some

SELECT distinct id, name, parentid
FROM test
CONNECT BY PRIOR id =parentid
START WITH id=50
order by 1 ;

(Edited Text)

SELECT 
distinct id, name, parentid,
    connect_by_root id          ,
    sys_connect_by_path(name,' > ') as full_path,
    CONNECT_BY_ROOT id cbr,
    CONNECT_BY_ISLEAF AS leaf    
FROM test
CONNECT BY PRIOR id =parentid
START WITH id=50
order by 1 ;

(Edited text) Expected Output :

51  C5  50 
100 C6  37 

CodePudding user response:

Here is one solution : you need to use nocycle option in the connect by clause to make oracle stop when encountering loops.

select distinct ID, NAME, PARENTID
from test
where class = 4
start with name = 'C4'
connect by nocycle prior id = parentid or prior parentid = parentid
order by id
;

CodePudding user response:

If you want to select all direct or indirect childs of the parent of id = 50 use simple a recursive CTE

with rec_cte (ID, NAME, PARENTID, CLASS) as (
 select * from test
 where parentid = (select parentid from test where id = 50)
  union all
 select test.ID, test.NAME, test.PARENTID, test.CLASS
 from rec_cte
 join test on rec_cte.id = test.parentid
)
select * from rec_cte

which gives as expected

        ID NAME    PARENTID      CLASS
---------- ----- ---------- ----------
        50 C4            37          2
       100 C6            37          4
       101 C7            37          5
        51 C5            50          4

If you want to restrict the above result to records with class = 4 add a filtering predicate

with rec_cte (ID, NAME, PARENTID, CLASS) as (
 select * from test
 where parentid = (select parentid from test where id = 50)
  union all
 select test.ID, test.NAME, test.PARENTID, test.CLASS
 from rec_cte
 join test on rec_cte.id = test.parentid
)
select ID, NAME, PARENTID
from rec_cte
where class = 4

This produces the result you expects

        ID NAME    PARENTID
---------- ----- ----------
       100 C6            37
        51 C5            50
  • Related