Как запросить все узлы между двумя узлами в дереве?

У меня есть иерархическая структура базы данных, например, столбцы ID а также PARENT_ID определяется для каждой строки, причем строки верхнего уровня имеют NULL PARENT_ID,

У меня все отношения из этой таблицы сведены в другую таблицу, например, если бы в одной иерархии деда, родителя, внука было три записи, было бы 3 записи:

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

Вместо того, чтобы выполнять иерархический запрос, чтобы определить, что внук является потомком деда, я могу просто проверить наличие (grandparent, grandchild) запись в этой сведенной таблице.

Мой вопрос, используя эту уплощенную таблицу, как я могу наиболее эффективно вернуть все записи, которые находятся между двумя узлами. Используя пример, с grandparent а также grandchild как мои параметры, как я могу получить обратно (grandparent, parent) запись.

Я не хочу использовать иерархический запрос для решения этого... Мне интересно, возможно ли это сделать без каких-либо объединений.

3 ответа

Решение
SELECT  *
FROM    mytable
WHERE   descendant = @descendant
        AND hops < 
        (
        SELECT  hops
        FROM    mytable
        WHERE   descendant = @descendant
                AND ancestor = @ancestor
        )

Это автоматически позаботится о случаях, когда @ancestor на самом деле не @descendantпредок.

Создать индекс на (descendant, hops) чтобы это работало быстро.

Пытаться:

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
                  )