sql >> Database >  >> RDS >> Oracle

Hiërarchieniveau en alle knooppuntreferenties op Oracle ophalen

Hier is een oplossing met een recursieve CTE. Ik gebruikte lvl als kolomkop sinds level is een gereserveerd woord in Oracle. U zult ook andere verschillen in terminologie zien. Ik gebruik "ouder" voor het onmiddellijk hogere niveau en "voorouder" voor>=0 stappen (om tegemoet te komen aan uw vereiste om een ​​knooppunt als zijn eigen voorouder te tonen). Ik gebruikte een ORDER BY clausule om ervoor te zorgen dat de uitvoer overeenkomt met die van u; u kunt de bestelde rijen wel of niet nodig hebben.

Uw vraag stimuleerde me om opnieuw, in meer detail, over hiërarchische queries te lezen, om te zien of dit hiermee kan worden gedaan in plaats van recursieve CTE's. Eigenlijk weet ik al dat je dat kunt, door CONNECT_BY_PATH . te gebruiken , maar met een substr op dat alleen maar het hoogste niveau in een hiërarchisch pad te halen is helemaal niet bevredigend, er moet een betere manier zijn. (Als dat de enige manier was om het te doen met hiërarchische zoekopdrachten, zou ik zeker de recursieve CTE-route gaan als deze beschikbaar was). Ik zal de hiërarchische zoekoplossing hier toevoegen, als ik een goede kan vinden.

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

Toegevoegd :Hiërarchische zoekoplossing

Oké - gevonden. Test beide oplossingen om te zien welke beter presteert; van tests op een andere setup was recursieve CTE een stuk sneller dan hiërarchische query's, maar dat kan van de specifieke situatie afhangen. OOK:recursieve CTE werkt alleen in Oracle 11.2 en hoger; de hiërarchische oplossing werkt met oudere versies.

Ik heb wat meer testgegevens toegevoegd die overeenkomen met die van 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


  1. Recursieve PL SQL Query Help

  2. Een eenvoudige gebruikersinterface maken om toegang te krijgen tot een Oracle-database

  3. Onderhoudstaken voor SQL-database uitvoeren met SQLCMD

  4. Een sleutel toevoegen aan een lege hstore-kolom