Oracle
 sql >> Database >  >> RDS >> Oracle

Ottieni il livello di gerarchia e tutti i riferimenti ai nodi su Oracle

Ecco una soluzione che utilizza un CTE ricorsivo. Ho usato lvl come intestazione di colonna dal level è una parola riservata in Oracle. Vedrai anche altre differenze nella terminologia. Uso "genitore" per il livello immediatamente superiore e "antenato" per>=0 passaggi (per soddisfare la tua esigenza di mostrare un nodo come proprio antenato). Ho usato un ORDER BY clausola per fare in modo che l'output corrisponda al tuo; potresti aver bisogno o meno delle righe ordinate.

La tua domanda mi ha stimolato a leggere di nuovo, in modo più dettagliato, le query gerarchiche, per vedere se questo può essere fatto con loro invece di CTE ricorsive. In realtà so già che puoi, usando CONNECT_BY_PATH , ma usando un substr sul fatto che solo recuperare il livello più alto in un percorso gerarchico non è affatto soddisfacente, ci deve essere un modo migliore. (Se questo fosse l'unico modo per farlo con query gerarchiche, seguirei sicuramente il percorso CTE ricorsivo se fosse disponibile). Aggiungerò qui la soluzione di query gerarchica, se riesco a trovarne una buona.

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

Aggiunto :Soluzione di query gerarchiche

OK - trovato. Si prega di testare entrambe le soluzioni per vedere quale funziona meglio; dai test su una configurazione diversa, CTE ricorsivo era un po' più veloce della query gerarchica, ma ciò potrebbe dipendere dalla situazione specifica. INOLTRE:CTE ricorsivo funziona solo in Oracle 11.2 e versioni successive; la soluzione gerarchica funziona con le versioni precedenti.

Ho aggiunto un po' più di dati di test in modo che corrispondano a quelli di Anatoliy.

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