sql >> Base de Datos >  >> RDS >> Oracle

Obtenga el nivel de jerarquía y todas las referencias de nodos en Oracle

Aquí hay una solución usando un CTE recursivo. Usé lvl como encabezado de columna desde level es una palabra reservada en Oracle. También verá otras diferencias en la terminología. Uso "padre" para el nivel inmediatamente superior y "antepasado" para>=0 pasos (para adaptarse a su requisito de mostrar un nodo como su propio antepasado). Usé un ORDER BY cláusula para hacer que la salida coincida con la suya; puede o no necesitar las filas ordenadas.

Su pregunta me animó a leer nuevamente, con más detalle, sobre consultas jerárquicas, para ver si esto se puede hacer con ellas en lugar de CTE recursivos. En realidad, ya sé que puedes, usando CONNECT_BY_PATH , pero usando un substr en eso, solo recuperar el nivel superior en una ruta jerárquica no es satisfactorio en absoluto, debe haber una mejor manera. (Si esa fuera la única forma de hacerlo con consultas jerárquicas, definitivamente elegiría la ruta CTE recursiva si estuviera disponible). Agregaré la solución de consulta jerárquica aquí, si puedo encontrar una buena.

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

Añadido :solución de consulta jerárquica

Bien, lo encontré. Pruebe ambas soluciones para ver cuál funciona mejor; a partir de pruebas en una configuración diferente, la CTE recursiva fue un poco más rápida que la consulta jerárquica, pero eso puede depender de la situación específica. TAMBIÉN:el CTE recursivo solo funciona en Oracle 11.2 y superior; la solución jerárquica funciona con versiones anteriores.

Agregué un poco más de datos de prueba para que coincidan con los de 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