Comment faire une requête pour tous les noeuds entre deux noeuds dans un arbre?
Question
I ont une strucutre de base de données hiérarchique, par exemple, colonnes ID
et PARENT_ID
définies pour chaque rangée, avec les lignes de premier niveau ayant une NULL PARENT_ID
.
J'ai toutes les relations de cette table aplatie dans une autre table, par exemple s'il y avait trois enregistrements dans une seule hiérarchie des grands-parents, parents, petits-enfants, il y aurait 3 enregistrements:
**ANCESTOR, DESCENDANT**
grantparent, parent
grandparent, grandchild
parent, grandchild
Au lieu 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 l'existence d'un enregistrement (grandparent, grandchild)
dans ce tableau aplaties.
Ma question est, en utilisant ce tableau aplaties, comment puis-je plus revenir efficacement tous les enregistrements qui sont entre deux noeuds. En utilisant l'exemple, avec grandparent
et grandchild
que mes paramètres, comment puis-je récupérer le dossier (grandparent, parent)
.
Je ne veux pas utiliser une requête hiérarchique pour résoudre ce ... Je me demande s'il est possible de le faire sans joint.
La solution
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 l'ancêtre d'un @descendant
.
Créer un index sur (descendant, hops)
pour que cela fonctionne rapidement.
Autres conseils
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
SELECT
distinct ancestor
FROM
hierarchy
WHERE descendant = :1 AND
ancestor IN (
SELECT
distinct descendant
FROM
hierarchy WHERE ancestor = :2
)