Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Holen Sie sich die Hierarchieebene und alle Knotenreferenzen auf Oracle

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