Вы можете использовать рекурсивный СО.Я сделал это с помощью Oracle 12c.Синтаксис может немного отличаться от другой СУБД.Я построил таблицу и заполнил ее данными с помощью следующего сценария:
create table parent_child (
parent integer,
child integer,
constraint parent_child_pk primary key (parent, child)
);
insert all
into parent_child values (1, 2)
into parent_child values (1, 3)
into parent_child values (3, 4)
into parent_child values (3, 5)
into parent_child values (2, 6)
into parent_child values (7, 8)
into parent_child values (7, 9)
select 1 from dual;
commit;
Затем я использую рекурсивный оператор WITH:
with descendants (node) as (
select 1 from dual -- root
union all
select child from descendants inner join parent_child on parent = node
)
select node from descendants order by node;
select 1 from dual
- это элемент привязки (базовый случайрекурсии).Он ставит 1 в таблицу descendants
.Вы можете использовать 3 или 7 вместо этого, как в вашем примере.Затем идет рекурсивный случай с select child from descendants inner join parent_child on parent = node
рекурсивным членом.Это означает, что мы берем новые узлы в потомках (что означает 1) и получаем все их дочерние элементы (что означает 2 и 3) и добавляем их в таблицу descendants
.Итак, теперь у нас есть 1, 2 и 3 в таблице.Мы снова начинаем использовать 2 и 3 в качестве новых узлов и получаем их дочерние элементы, которые равны 4 и 5. Затем мы получаем полный результат, который, вероятно, является тем, что вы хотите.
Мы можем использовать listagg
, если нам нужна строкано тогда нам нужен способ упорядочить вещи или хотя бы способ идентифицировать корневой узел.Обратите внимание, что не очень хорошая идея объединять кортежи в таблице как одну большую строку.
with descendants (node, is_root) as (
select 1, 'Y' from dual -- root
union all
select child, 'N' from descendants inner join parent_child on parent = node
)
select '(' || listagg(node, ', ') within group (order by case is_root when 'Y' then 0 else 1 end, node) || ')' list
from descendants;
, что дает (1, 2, 3, 4, 5, 6)
.