Hier ist eine Lösung mit einem rekursiven CTE. Ich habe lvl
verwendet als Spaltenüberschrift seit level
ist ein reserviertes Wort in Oracle. Sie werden auch andere Unterschiede in der Terminologie feststellen. Ich verwende „parent“ für die unmittelbar höhere Ebene und „ancestor“ für>=0 Schritte (um Ihrer Anforderung gerecht zu werden, einen Knoten als seinen eigenen Vorfahren anzuzeigen). Ich habe einen ORDER BY
verwendet -Klausel, damit die Ausgabe mit Ihrer übereinstimmt; Sie können die bestellten Zeilen benötigen oder nicht.
Ihre Frage hat mich dazu angeregt, noch einmal ausführlicher über hierarchische Abfragen zu lesen, um zu sehen, ob dies mit ihnen anstelle von rekursiven CTEs möglich ist. Eigentlich weiß ich bereits, dass Sie das können, indem Sie CONNECT_BY_PATH
verwenden , aber mit einem substr
Nur die oberste Ebene in einem hierarchischen Pfad abzurufen ist überhaupt nicht zufriedenstellend, es muss einen besseren Weg geben. (Wenn dies der einzige Weg wäre, dies mit hierarchischen Abfragen zu tun, würde ich definitiv den rekursiven CTE-Weg gehen, wenn er verfügbar wäre). Ich werde die hierarchische Abfragelösung hier hinzufügen, wenn ich eine gute finde.
with h ( node, parent ) as (
select 1 , null from dual union all
select 2 , 1 from dual union all
select 3 , 2 from dual
),
r ( node , ancestor, steps ) as (
select node , node , 0
from h
union all
select r.node, h.parent, steps + 1
from h join r
on h.node = r.ancestor
)
select node, ancestor,
1+ (max(steps) over (partition by node)) as lvl, steps
from r
where ancestor is not null
order by lvl, steps desc;
NODE ANCESTOR LVL STEPS
---------- ---------- ---------- ----------
1 1 1 0
2 1 2 1
2 2 2 0
3 1 3 2
3 2 3 1
3 3 3 0
Hinzugefügt :Hierarchische Abfragelösung
Okay - gefunden. Bitte testen Sie beide Lösungen, um zu sehen, welche besser funktioniert; Bei Tests mit einem anderen Setup war der rekursive CTE um einiges schneller als die hierarchische Abfrage, aber das kann von der jeweiligen Situation abhängen. AUCH:rekursiver CTE funktioniert nur in Oracle 11.2 und höher; die hierarchische Lösung funktioniert mit älteren Versionen.
Ich habe ein bisschen mehr Testdaten hinzugefügt, um mit denen von Anatoliy übereinzustimmen.
with h ( node, parent ) as (
select 1 , null from dual union all
select 2 , 1 from dual union all
select 3 , 2 from dual union all
select 4 , 2 from dual union all
select 5 , 4 from dual
)
select node,
connect_by_root node as ancestor,
max(level) over (partition by node) as lvl,
level - 1 as steps
from h
connect by parent = prior node
order by node, ancestor;
NODE ANCESTOR LVL STEPS
---------- ---------- ---------- ----------
1 1 1 0
2 1 2 1
2 2 2 0
3 1 3 2
3 2 3 1
3 3 3 0
4 1 3 2
4 2 3 1
4 4 3 0
5 1 4 3
5 2 4 2
5 4 4 1
5 5 4 0