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

Få Hierarki-niveau og alle nodereferencer på Oracle

Her er en løsning ved hjælp af en rekursiv CTE. Jeg brugte lvl som kolonneoverskrift siden level er et reserveret ord i Oracle. Du vil også se andre forskelle i terminologi. Jeg bruger "forælder" for det umiddelbart højere niveau og "forfader" for>=0 trin (for at imødekomme dit krav om at vise en node som sin egen forfader). Jeg brugte en ORDER BY klausul for at få outputtet til at matche dit; du har muligvis brug for rækkerne bestilt eller ikke.

Dit spørgsmål stimulerede mig til igen at læse mere detaljeret om hierarkiske forespørgsler for at se, om dette kan gøres med dem i stedet for rekursive CTE'er. Faktisk ved jeg allerede, at du kan, ved at bruge CONNECT_BY_PATH , men ved at bruge en substr på, at bare at hente det øverste niveau i en hierarkisk vej slet ikke er tilfredsstillende, må der være en bedre måde. (Hvis det var den eneste måde at gøre det på med hierarkiske forespørgsler, ville jeg helt sikkert gå den rekursive CTE-vej, hvis den var tilgængelig). Jeg vil tilføje den hierarkiske forespørgselsløsning her, hvis jeg kan finde en god.

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

Tilføjet :Hierarkisk forespørgselsløsning

OK - fandt det. Test venligst begge løsninger for at se, hvilken der klarer sig bedst; fra test på en anden opsætning var rekursiv CTE en del hurtigere end hierarkisk forespørgsel, men det kan afhænge af den specifikke situation. OGSÅ:rekursiv CTE virker kun i Oracle 11.2 og nyere; den hierarkiske løsning fungerer med ældre versioner.

Jeg tilføjede lidt flere testdata for at matche Anatoliys.

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. Præstationsproblemer:Det første møde

  2. MySQL:Find rækker, der ikke deltager i et forhold

  3. Uventet effekt af filtrering på resultat fra crosstab()-forespørgsel

  4. Vælg et dynamisk sæt af kolonner fra en tabel og få summen for hver