Oracle
 sql >> Base de données >  >> RDS >> Oracle

Obtenir le niveau hiérarchique et toutes les références de nœud sur Oracle

Voici une solution utilisant un CTE récursif. J'ai utilisé lvl comme en-tête de colonne depuis level est un mot réservé dans Oracle. Vous verrez également d'autres différences de terminologie. J'utilise "parent" pour le niveau immédiatement supérieur et "ancêtre" pour>=0 étapes (pour répondre à votre exigence d'afficher un nœud comme son propre ancêtre). J'ai utilisé un ORDER BY clause pour que la sortie corresponde à la vôtre ; vous pouvez ou non avoir besoin des lignes commandées.

Votre question m'a incité à relire, plus en détail, les requêtes hiérarchiques, pour voir si cela peut être fait avec elles au lieu de CTE récursifs. En fait, je sais déjà que vous pouvez, en utilisant CONNECT_BY_PATH , mais en utilisant une substr là-dessus, récupérer le niveau supérieur dans un chemin hiérarchique n'est pas du tout satisfaisant, il doit y avoir un meilleur moyen. (Si c'était la seule façon de le faire avec des requêtes hiérarchiques, j'opterais certainement pour la voie CTE récursive si elle était disponible). J'ajouterai la solution de requête hiérarchique ici, si je peux en trouver une bonne.

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

Ajouté :Solution de requête hiérarchique

OK - trouvé. Veuillez tester les deux solutions pour voir laquelle fonctionne le mieux ; à partir de tests sur une configuration différente, le CTE récursif était un peu plus rapide que la requête hiérarchique, mais cela peut dépendre de la situation spécifique. AUSSI :le CTE récursif ne fonctionne que dans Oracle 11.2 et versions ultérieures ; la solution hiérarchique fonctionne avec les anciennes versions.

J'ai ajouté un peu plus de données de test pour correspondre à celles d'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