В основном вы ищете циклов в своей таблице.
Функциональность Oracle для идентификации циклов в иерархическом запросе:
CONNECT BY NOCYCLE
и CONNECT_BY_ISCYCLE
В этом запросе отображаются все узлы, ведущие к циклу - столбец is_Cycle = 1
select tbl.* ,
CONNECT_BY_ISCYCLE is_Cycle,
SYS_CONNECT_BY_PATH(childid, '/') path
from tbl
CONNECT BY NOCYCLE PRIOR childid = parentid
Для ваших данных результат равен
PARENTID CHILDID IS_CYCLE PATH
---------- ---------- ---------- ----------
1 2 0 /2
2 1 1 /2/1
1 3 1 /2/1/3
1 3 0 /3
3 1 1 /3/1
1 2 1 /3/1/2
2 1 0 /1
1 2 1 /1/2
1 3 1 /1/3
3 1 0 /1
1 2 1 /1/2
1 3 1 /1/3
Примечаниекаждый цикл распознается в нескольких местах, поэтому вы получаете избыточные данные.
Преимущество этого метода в том, что он работает и для более длинных циклов (где простой подход GROUP BY не работает).
Пример для цикла длиной 3:
create table tbl as
select 1 parentid, 2 childid from dual union all
select 2 parentid, 3 childid from dual union all
select 3 parentid, 1 childid from dual;
PARENTID CHILDID IS_CYCLE PATH
---------- ---------- ---------- ----------
1 2 0 /2
2 3 0 /2/3
3 1 1 /2/3/1
2 3 0 /3
3 1 0 /3/1
1 2 1 /3/1/2
3 1 0 /1
1 2 0 /1/2
2 3 1 /1/2/3