sqloracle-databaseconnect-byhierarchical-query

hierarchical query without side rows


I have "id-parent_id related" data, like this:

      1
     / \
    /   \
   2     4
  /
 /
3

I have the code, that returns data for all rows related to particular (related to condition in the start with clause) tree - in both sides ("up" and "down"), for example:

with
  temp_cte(id, parent_id) as
    (select 1, null from dual
     union all
     select 2, 1 from dual
     union all
     select 3, 2 from dual
     union all
     select 4, 1 from dual
     union all
     select 5, null from dual)
select *
from temp_cte t
connect by nocycle (prior id = parent_id) or (prior parent_id = id)
start with t.id = 2
order by id

How do i get data without "side" ("right"/"left") rows? e.g. for the drawn above -

I need data without 4 when I start with 2 or 3,

and I need data without 2 and 3 when I start with 4

(if start with 1, I still want the full tree)


Solution

  • This is because of OR predicate in CONNECT BY: your query traverses in both directions, so on the second step of CONNECT BY you'll have all the childs of the parent and finally all the tree.

    You need to split the query into union of two directions.

    with
      temp_cte(id, parent_id) as
        (select 1, null from dual
         union all
         select 2, 1 from dual
         union all
         select 3, 2 from dual
         union all
         select 4, 1 from dual
         union all
         select 5, null from dual
    )
    
    select id, parent_id
    from temp_cte t
    where level > 1
    connect by nocycle (prior id = parent_id)
    start with t.id = 2
    
    union all
    
    select id, parent_id
    from temp_cte t
    connect by (prior parent_id = id)
    start with t.id = 2
    order by id
    
    ID | PARENT_ID
    -: | --------:
     1 |      null
     2 |         1
     3 |         2
    

    db<>fiddle here