Вы можете использовать иерархический запрос со встроенным представлением, который сначала объединяет соответствующие таблицы. Запрос для встроенного представления может быть:
select p.person_id, pn.first_name, c.person_father_id
from person p
join person_name pn on pn.person_id = p.person_id
left join children c on c.person_child_id = p.person_id;
PERSON_ID FIRST_NAME PERSON_FATHER_ID
---------- ---------- ----------------
2 Lautaro 1
3 Lucas 2
4 Franco 3
5 Agustín 4
1 Santiago
и с этим в качестве основы для иерархического запроса:
select trim(sys_connect_by_path(first_name, ' ')) as whole_name
from (
select p.person_id, pn.first_name, c.person_father_id
from person p
join person_name pn on pn.person_id = p.person_id
left join children c on c.person_child_id = p.person_id
)
where connect_by_isleaf = 1
start with person_id = 4
connect by person_id = prior person_father_id;
WHOLE_NAME
--------------------------------------------------
Franco Lucas Lautaro Santiago
Или вы можете сделать иерархический запрос сам по себе дополнительным подзапросом, а затем присоединиться к именам и объединить это:
select listagg(pn.first_name, ' ') within group (order by lvl) as whole_name
from (
select person_id, level as lvl
from (
select p.person_id, c.person_father_id
from person p
left join children c on c.person_child_id = p.person_id
)
start with person_id = 4
connect by person_id = prior person_father_id
) t
join person_name pn on pn.person_id = t.person_id;
WHOLE_NAME
--------------------------------------------------
Franco Lucas Lautaro Santiago
Обратите внимание, что с обоими из них вы должны присоединиться к таблицам, прежде чем сможете выполнять фильтрацию по начальному идентификатору (start with
, а не where
, поскольку это иерархически). Это означает, что с большими таблицами это может привести к тому, что вы будете выполнять больше работы, чем вам действительно нужно или ожидаете.
Или вы можете сделать то же самое с рекурсивным факторингом подзапроса (рекурсивный CTE), если вы предпочитаете, и вы используете Oracle 11gR2 или выше:
with r (person_id, person_father_id, lvl) as (
select p.person_id, c.person_father_id, 1
from person p
left join children c on c.person_child_id = p.person_id
where p.person_id = 4
union all
select p.person_id, c.person_father_id, r.lvl + 1
from r
join person p on p.person_id = r.person_father_id
left join children c on c.person_child_id = p.person_id
)
select listagg(pn.first_name, ' ') within group (order by lvl) as whole_name
from r
join person_name pn on pn.person_id = r.person_id;
WHOLE_NAME
--------------------------------------------------
Franco Lucas Lautaro Santiago
, который выглядит более сложным, но может, по крайней мере, поместить фильтр в элемент привязки рекурсивного CTE.
Подробнее о иерархических запросах и рекурсивных факторингах подзапросов .