Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Obtenha o nível de hierarquia e todas as referências de nós no Oracle


Aqui está uma solução usando um CTE recursivo. Eu usei lvl como cabeçalho de coluna desde level é uma palavra reservada no Oracle. Você também verá outras diferenças na terminologia. Eu uso "pai" para o nível imediatamente mais alto e "ancestral" para>=0 etapas (para acomodar sua exigência de mostrar um nó como seu próprio ancestral). Eu usei um ORDER BY cláusula para fazer com que a saída corresponda à sua; você pode ou não precisar das linhas ordenadas.

Sua pergunta me estimulou a ler novamente, com mais detalhes, sobre consultas hierárquicas, para ver se isso pode ser feito com elas ao invés de CTEs recursivas. Na verdade, eu já sei que você pode, usando CONNECT_BY_PATH , mas usando um substr em que apenas para recuperar o nível superior em um caminho hierárquico não é satisfatório, deve haver uma maneira melhor. (Se essa fosse a única maneira de fazer isso com consultas hierárquicas, eu definitivamente seguiria a rota CTE recursiva se estivesse disponível). Vou adicionar a solução de consulta hierárquica aqui, se eu encontrar uma boa.
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

Adicionado :Solução de consulta hierárquica

OK - encontrei. Por favor, teste ambas as soluções para ver qual tem melhor desempenho; a partir de testes em uma configuração diferente, a CTE recursiva foi um pouco mais rápida que a consulta hierárquica, mas isso pode depender da situação específica. TAMBÉM:o CTE recursivo funciona apenas no Oracle 11.2 e superior; a solução hierárquica funciona com versões mais antigas.

Eu adicionei um pouco mais de dados de teste para corresponder aos 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