Reputation: 49
I'm new to recursive queries so apologies if this is a simple solution but I'm thinking it will be a bit harder.
I've been given a hierarchy table that has multiple levels of parent-child relationships defined and I need a way to show all possible relationships that one item can have. There are also circular relationships that I cannot get rid of - I am unsure if this will cause issues.
For example, the original data would look like this:
PN INT
===== =====
ABC1 ABC2
ABC1 ABC9
ABC2 ABC3
ABC3 ABC4
DEF1 DEF2
GHI1 GHI2
GHI2 GHI1
I need the result of the query to look like this:
PN INT
===== =====
ABC1 ABC2
ABC1 ABC9
ABC1 ABC3
ABC1 ABC4
ABC2 ABC3
ABC2 ABC4
ABC3 ABC4
DEF1 DEF2
GHI1 GHI2
GHI2 GHI1
My approach so far has been joining the table back on itself as many times as required until I have the entire relationship defined (ie. every single child/INT of the original parent/PN) but I'm hoping there is a better way using recursive queries.
Hoping this makes sense and thanks in advance!
Upvotes: 0
Views: 1485
Reputation: 9875
Build the hierarchy for every row, returning the value for pn
for the root rows.
You can do this with connect by
using connect_by_root
:
create table t (
c1 varchar2(4), c2 varchar2(4)
);
insert into t values ( 'ABC1', 'ABC2' );
insert into t values ( 'ABC1', 'ABC9' );
insert into t values ( 'ABC2', 'ABC3' );
insert into t values ( 'ABC3', 'ABC4' );
insert into t values ( 'DEF1', 'DEF2' );
insert into t values ( 'GHI1', 'GHI2' );
insert into t values ( 'GHI2', 'GHI1' );
commit;
select * from (
select distinct connect_by_root c1 rt, c2
from t
connect by nocycle c1 = prior c2
)
where rt <> c2
order by rt, c2;
RT C2
ABC1 ABC2
ABC1 ABC3
ABC1 ABC4
ABC1 ABC9
ABC2 ABC3
ABC2 ABC4
ABC3 ABC4
DEF1 DEF2
GHI1 GHI2
GHI2 GHI1
The nocycle
clause detects loops and stops processing.
Or recursive with
by selecting the value of the root on each iteration:
with tree ( c1, c2, rt ) as (
select c1, c2, c1 from t
union all
select t.c1, t.c2, tree.rt
from tree
join t
on t.c1 = tree.c2
) cycle c1 set is_cycle to 'Y' default 'N'
select rt, c2
from tree
where is_cycle = 'N'
and rt <> c2
order by rt, c2;
RT C2
ABC1 ABC2
ABC1 ABC3
ABC1 ABC4
ABC1 ABC9
ABC2 ABC3
ABC2 ABC4
ABC3 ABC4
DEF1 DEF2
GHI1 GHI2
GHI2 GHI1
The cycle
clause detects loops.
Upvotes: 1