ads
ads

Reputation: 1723

Oracle Hierarchy - How to get a particular level record in a query?

We have the following structure for Organizations.

create table orgs (
    org_id number
  , org_name varchar2(250)
  , org_type varchar2(10)
  , parent_org_id number 
)
/

insert into orgs values ( 1, 'President', 'PRES', null );
insert into orgs values ( 2, 'Information Technology Department', 'DEP', 1 );
insert into orgs values ( 3, 'Software Development Division', 'DIV', 2 );
insert into orgs values ( 4, 'Database Unit', 'UNIT', 3 );
insert into orgs values ( 5, 'Developer Unit', 'UNIT', 3 );
insert into orgs values ( 6, 'Infrastracture Department', 'DEP', 1 );
insert into orgs values ( 7, 'Security Division', 'DIV', 6 );
insert into orgs values ( 8, 'System Admintrator Division', 'UNIT', 7 );


  select level, org_id, org_name, org_type
    from orgs
 connect
      by 
   prior org_id = parent_org_id
   start
    with parent_org_id is null

Query returns the result

enter image description here

What I'm trying to do is let's say I need to get the Department (Information Technology Department) of org_id 4 (Database Unit), how should I build the query for that?

Currently we built a function that returns the department id which basically loops until it reaches the DEP parent. But it has a performance issue.

Upvotes: 1

Views: 706

Answers (2)

markusk
markusk

Reputation: 6667

You can invert the hierarchy query to start from the Database Unit (org_id = 4) and filter to the department ancestor (org_type = 'DEP'):

select org_id, org_name
from orgs
where org_type = 'DEP'
connect by prior parent_org_id = org_id
start with org_id = 4;

The where clause is applied after the hierarchy is retrieved.

Upvotes: 2

gsalem
gsalem

Reputation: 2028

You can try something like this (replace the '5' with what you want as starting org_id):

with lp (lev, org_id, org_name, org_type, parent_org_id, l_orgs) as (
select 1 as lev, org_id, org_name, org_type, parent_org_id , to_char(org_id) l_orgs
    from orgs
    where org_id=5
union all
select lev+1, o.org_id, o.org_name, l.org_type||'/'||o.org_type, o.parent_org_id, l_orgs||'/'||o.org_id
from orgs o join  lp l on (o.org_id=l.parent_org_id and l.org_type not like '%DEP'))
select lev, org_id, org_name, org_type, l_orgs
from lp;

This will give you something like this:

LEV    ORG_ID ORG_NAME                          ORG_TYPE            L_orgs
-----  ------ --------------------------------- --------            ------
    1   5     Developer Unit                    UNIT                5
    2   3     Software Development Division     UNIT/DIV            5/3
    3   2     Information Technology Department UNIT/DIV/DEP        5/3/2

Upvotes: 0

Related Questions