Как получить все значения в иерархии, связанные с некоторым значением, используя 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);