2

J'ai une structure de base de données hiérarchique, par ex. colonnes ID et PARENT_ID définies pour chaque ligne, les lignes de niveau supérieur ayant un NULL PARENT_ID.Comment interroger tous les nœuds entre deux nœuds d'un arbre?

J'ai toutes les relations de cette table aplaties dans une autre table, par ex. s'il y avait trois enregistrements dans une seule hiérarchie des grands-parents, parents, petits-enfants, il y aurait 3 dossiers:

**ANCESTOR, DESCENDANT** 
grantparent, parent 
grandparent, grandchild 
parent, grandchild 

Plutôt que d'exécuter une requête hiérarchique pour déterminer que le petit-fils est un descendant du grand-parent, je peux simplement vérifier pour l'existence d'un enregistrement (grandparent, grandchild) dans cette table aplatie.

Ma question est, en utilisant cette table aplatie, comment puis-je retourner le plus efficacement tous les enregistrements qui se trouvent entre deux nœuds. En utilisant l'exemple, avec grandparent et grandchild comme mes paramètres, comment puis-je récupérer l'enregistrement (grandparent, parent).

Je ne veux pas utiliser une requête hiérarchique pour résoudre ce problème ... Je me demande s'il est possible de le faire sans jointures.

+0

Vos hiérarchies réelles ne sont probablement pas limitées à trois niveaux? –

+0

@Renderln, est-ce que votre table aplatie * seulement * inclut les colonnes Ancêtre et Descendant, ou y a-t-il d'autres colonnes (telles que le nombre de générations/niveaux) incluses? Aussi, peut-il y avoir plusieurs façons de lier un descendant au même ancêtre? –

+0

@Ed Harper: Oui, cette table contient plusieurs hiérarchies de différents niveaux. –

Répondre

2
SELECT * 
FROM mytable 
WHERE descendant = @descendant 
     AND hops < 
     (
     SELECT hops 
     FROM mytable 
     WHERE descendant = @descendant 
       AND ancestor = @ancestor 
     ) 

Cela prendra automatiquement en charge des cas quand @ancestor est pas vraiment un ancêtre » @descendant. Créer un index sur (descendant, hops) pour que cela fonctionne rapidement.

1

Essayez:

select h1.descendant intermediate_node 
from hierarchy h0 
join hierarchy h1 
    on h0.ancestor = h1.ancestor 
and h0.hops > h1.hops -- redundant condition, but may improve performance 
join hierarchy h2 
    on h1.ancestor = h2.ancestor 
and h0.descendant = h2.descendant 
where h0.ancestor = :ancestor and h0.descendant = :descendant 
0
SELECT 
    distinct ancestor 
FROM 
    hierarchy 
WHERE descendant = :1 AND 
     ancestor IN (
        SELECT 
         distinct descendant 
        FROM 
         hierarchy WHERE ancestor = :2 
       )