Как получить все значения в иерархии, связанные с некоторым значением, используя Oracle CONNECT BY

модель отношения

1   3   
  / 
  2   4
   
    7   5     8
      /     /
      6     9

стол :

select 2 child, 1 father from dual
union all
select 2 child, 3 father from dual
union all
select 4 child, 3 father from dual
union all
select 7 child, 2 father from dual
union all
select 6 child, 5 father from dual
union all
select 6 child, 7 father from dual
union all
select 9 child, 8 father from dual

как я могу получить все значения, связанные со значением CHILD или FATHER = 2 ?

должно быть

1,2,3,4,5,6,7

, а не

8,9

поскольку он не связан со значением 2.

как достичь этого с помощью инструкции CONNECT BY? Спасибо.

p.s. это решение очень близко ко мне, но не работает для моей модели:

найти все узлы в модель списка смежности с oracle connect by

версия DB-10.2.0.5.0

модель-с-oracle-connect-by

таким образом, стратегия может быть примерно такой (например, начать с node=7):

Шаг 1 (направление = вверх)

select t1.father,connect_by_root father as root,connect_by_isleaf from 
(my_table) t1
start with father=7
connect by prior father = child 

результат 7,2,1,3, где 1,3-корень высокого уровня (isleaf=1)

Шаг 2 (получить маршрут для 1,3 направления=вниз)

select t1.child,connect_by_root father as root,connect_by_isleaf from 
(my_table) t1
start with father=1
connect by father = prior child 

результат 2,7,6 где 6 низкоуровневый корень (isleaf=1)

select t1.child,connect_by_root father as root,connect_by_isleaf from 
(my_table) t1
start with father=3
connect by father = prior child

результат 2,7,6,4, где 6,4-корень низкого уровня (isleaf=1)

Шаг 3 (получить маршрут для направления 6,4 = вверх)

select t1.father,connect_by_root father as root,connect_by_isleaf from 
(my_table) t1
start with child=6
connect by prior father = child 

результат 5,7,2,1,3, где 5,1,3-корень высокого уровня (isleaf=1) Является ли этот результат я нашел node=5

затем я должен изменить направление вниз.. потом снова вверх.. потом снова вниз..

но как объединить все эти шаги в одном выборе ? Это очень тяжело для бегинера . Помогите мне, пожалуйста.

3 ответов


для вывода вам не нужно направлять график, поэтому добавьте обратные ссылки ко всем существующим ссылкам. Это то, что я делаю в подзапросе "bi". Затем вы используете nocyle connect by query.

    with h as (
                     SELECT 2 child, 1 father FROM dual
                     UNION ALL
                     SELECT 2 child, 3 father FROM dual
                     UNION ALL
                     SELECT 4 child, 3 father FROM dual
                     UNION ALL
                     SELECT 7 child, 2 father FROM dual
                     UNION ALL
                     SELECT 6 child, 5 father FROM dual
                     UNION ALL
                     SELECT 6 child, 7 father FROM dual
                     UNION ALL
                     SELECT 9 child, 8 father FROM dual
            ),
    bi as (select * from h union all select father , child from h )     
    select distinct father from bi
    start with child = 2
    connect by nocycle
    prior father = child

Я использую нотацию "with" для запроса для лучшей читаемости.


Это то, что вы просите:

SELECT     child
FROM       (
             SELECT 2 child, 1 father FROM dual
             UNION ALL
             SELECT 2 child, 3 father FROM dual
             UNION ALL
             SELECT 4 child, 3 father FROM dual
             UNION ALL
             SELECT 7 child, 2 father FROM dual
             UNION ALL
             SELECT 6 child, 5 father FROM dual
             UNION ALL
             SELECT 6 child, 7 father FROM dual
             UNION ALL
             SELECT 9 child, 8 father FROM dual
           )
START WITH father IN ( SELECT  father
                       FROM     
                       (
                                   SELECT 2 child, 1 father FROM dual
                                   UNION ALL
                                   SELECT 2 child, 3 father FROM dual
                                   UNION ALL
                                   SELECT 4 child, 3 father FROM dual
                                   UNION ALL
                                   SELECT 7 child, 2 father FROM dual
                                   UNION ALL
                                   SELECT 6 child, 5 father FROM dual
                                   UNION ALL
                                   SELECT 6 child, 7 father FROM dual
                                   UNION ALL
                                   SELECT 9 child, 8 father FROM dual
                        )
                       START WITH child = 2
                       CONNECT BY PRIOR father = child)
CONNECT BY PRIOR child = father
UNION
SELECT     father
FROM       (
SELECT 2 child, 1 father FROM dual
UNION ALL
SELECT 2 child, 3 father FROM dual
UNION ALL
SELECT 4 child, 3 father FROM dual
UNION ALL
SELECT 7 child, 2 father FROM dual
UNION ALL
SELECT 6 child, 5 father FROM dual
UNION ALL
SELECT 6 child, 7 father FROM dual
UNION ALL
SELECT 9 child, 8 father FROM dual
          )
START WITH child IN (
SELECT     child
FROM       (
             SELECT 2 child, 1 father FROM dual
             UNION ALL
             SELECT 2 child, 3 father FROM dual
             UNION ALL
             SELECT 4 child, 3 father FROM dual
             UNION ALL
             SELECT 7 child, 2 father FROM dual
             UNION ALL
             SELECT 6 child, 5 father FROM dual
             UNION ALL
             SELECT 6 child, 7 father FROM dual
             UNION ALL
             SELECT 9 child, 8 father FROM dual
           )
        START WITH child = 2
          CONNECT BY PRIOR child = father)


CONNECT BY PRIOR father = child;

этот запрос состоит из двух блоков. Первый блок извлекает всех детей всех отцов 2 (параметр), второй блок (с объединением, чтобы избежать дубликатов) извлекает всех отцов всех детей 2.


если я вас правильно понял , вы можете использовать функцию connect_by_root, как показано ниже :

select hier.child , hier.father
from 
(
  select t.* , connect_by_root(father) top_father
  from 
  (
    select 2 child, 1 father from dual
    union all
    select 2 child, 3 father from dual
    union all
    select 4 child, 3 father from dual
    union all
    select 7 child, 2 father from dual
    union all
    select 6 child, 5 father from dual
    union all
    select 6 child, 7 father from dual
    union all
    select 9 child, 8 father from dual
  ) t
  connect by t.child = prior t.father
) hier
where 2 in (hier.child , hier.top_father);