with w(child, parent) as
(
select 'A', null from dual
union all
select 'A1', 'A' from dual
union all
select 'A11', 'A1' from dual
union all
select 'A2', 'A' from dual
union all
select 'B', null from dual
union all
select 'B1', 'B' from dual
union all
select 'B2', 'B' from dual
union all
select 'B21', 'B2' from dual
union all
select 'B22', 'B2' from dual
)
select connect_by_root child parent, child
from w
connect by w.parent = prior w.child
start with w.parent is null
;
This returns:
1 A A
2 A A1
3 A A11
4 A A2
5 B B
6 B B1
7 B B2
8 B B21
9 B B22
You can filter lines with parent == child by adding where connect_by_root child != child
between the from
and the connect
.