sql >> Databasteknik >  >> RDS >> Oracle

Få hierarkinivå och alla nodreferenser på Oracle

Här är en lösning som använder en rekursiv CTE. Jag använde lvl som kolumnrubrik sedan level är ett reserverat ord i Oracle. Du kommer att se andra skillnader i terminologi också. Jag använder "förälder" för den omedelbart högre nivån och "förfader" för>=0 steg (för att tillgodose ditt krav på att visa en nod som sin egen förfader). Jag använde en ORDER BY klausul för att få utdata att matcha din; du kanske behöver raderna ordnade eller inte.

Din fråga stimulerade mig att återigen läsa mer i detalj om hierarkiska frågor, för att se om detta kan göras med dem istället för rekursiva CTE. Jag vet faktiskt redan att du kan, genom att använda CONNECT_BY_PATH , men med en substr på att bara att hämta den översta nivån i en hierarkisk väg inte är tillfredsställande alls, det måste finnas ett bättre sätt. (Om det var det enda sättet att göra det med hierarkiska frågor, skulle jag definitivt gå den rekursiva CTE-vägen om den var tillgänglig). Jag kommer att lägga till den hierarkiska frågelösningen här, om jag kan hitta en bra.

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

Tillagt :Hierarkisk frågelösning

OK - hittade den. Testa båda lösningarna för att se vilken som fungerar bäst; från tester på en annan inställning var rekursiv CTE ganska mycket snabbare än hierarkisk fråga, men det kan bero på den specifika situationen. ÄVEN:rekursiv CTE fungerar endast i Oracle 11.2 och senare; den hierarkiska lösningen fungerar med äldre versioner.

Jag lade till lite mer testdata för att matcha 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. Oracle JDBC intermittent anslutningsproblem

  2. SQL Server-motsvarighet till substring_index-funktionen i MySQL

  3. Hur man skapar en trigger för att ta bort php myadmin

  4. phpActiveRecord Felaktigt DateTimeFormat