Я использую Oracle 12c.
У меня есть иерархическая таблица Oracle, в которой я хотел бы использовать короткое имя родительского узла (например, start with parent_node_is is null)
для всех дочерних узлов, принадлежащих этому родителю.
Например: Имя таблицы: nodes_tab
NODE_ID SHORT_NAME PARENT_NODE_ID
---------- -------------- --------------
1 Parent Node-1 NULL
2 Child Node-2 1
3 Child Node-3 1
4 Child Node-4 2
5 Child Node-5 2
6 Child Node-6 4
7 Child Node-7 6
Чего я хотел бы добиться, так это запросить вышеуказанную вкладку nodes_tab для всех node_ids, но назначить short_name, принадлежащий родительскому узлу.
В идеале я просто хочу повторить одно и то же имя Parent Node-1 для остальных node_id от 2 до 7, но не знаю, каким должен быть SQL-запрос. Я посмотрел на LAG, но, похоже, он не помогает.
Результат, который мне нужен:
NODE_ID SHORT_NAME
---------- -------------
1 Parent Node-1
2 Parent Node-1
3 Parent Node-1
4 Parent Node-1
5 Parent Node-1
6 Parent Node-1
7 Parent Node-1
То, что я ищу, - это просто запрос, который использует короткое имя строки, где parent_node_id is NULL, и повторяет это короткое имя для всех других записей, где parent_node_id is NOT NULL


Иерархически ваши данные выглядят так:
SQL> with nodes_tab (node_id, short_name, parent_node_id) as
2 (select 1, 'Parent Node-1', null from dual union all
3 select 2, 'Child Node-2' , 1 from dual union all
4 select 3, 'Child Node-3' , 1 from dual union all
5 select 4, 'Child Node-4' , 2 from dual union all
6 select 5, 'Child Node-5' , 2 from dual union all
7 select 6, 'Child Node-6' , 4 from dual union all
8 select 7, 'Child Node-7' , 6 from dual
9 )
10 select node_id,
11 lpad(' ', 2 * level) || short_name as short_name,
12 parent_node_id,
13 connect_by_root short_name as root_node
14 from nodes_tab
15 start with parent_node_id is null
16 connect by prior node_id = parent_node_id;
NODE_ID SHORT_NAME PARENT_NODE_ID ROOT_NODE
---------- ------------------------- -------------- -------------
1 Parent Node-1 Parent Node-1
2 Child Node-2 1 Parent Node-1
4 Child Node-4 2 Parent Node-1
6 Child Node-6 4 Parent Node-1
7 Child Node-7 6 Parent Node-1
5 Child Node-5 2 Parent Node-1
3 Child Node-3 1 Parent Node-1
7 rows selected.
SQL>
Обратите внимание на ROOT_NODE, который извлекается с помощью CONNECT_BY_ROOT — похоже, вам нужно это значение для всех SHORT_NAME.
Итак: если мы удалим отступ и применим то, что мы видели выше, вместе с соответствующим предложением ORDER BY, окончательный результат будет
SQL> with nodes_tab (node_id, short_name, parent_node_id) as
2 (select 1, 'Parent Node-1', null from dual union all
3 select 2, 'Child Node-2' , 1 from dual union all
4 select 3, 'Child Node-3' , 1 from dual union all
5 select 4, 'Child Node-4' , 2 from dual union all
6 select 5, 'Child Node-5' , 2 from dual union all
7 select 6, 'Child Node-6' , 4 from dual union all
8 select 7, 'Child Node-7' , 6 from dual
9 )
10 select node_id,
11 connect_by_root short_name as short_name
12 from nodes_tab
13 start with parent_node_id is null
14 connect by prior node_id = parent_node_id
15 order by node_id;
NODE_ID SHORT_NAME
---------- -------------------------
1 Parent Node-1
2 Parent Node-1
3 Parent Node-1
4 Parent Node-1
5 Parent Node-1
6 Parent Node-1
7 Parent Node-1
7 rows selected.
SQL>
Oracle 11GR2 и более поздние версии поддерживают рекурсивные CTE (которые являются частью стандартного SQL).
Итак, это работает:
with cte (node_id, parent_id, short_name, lev) as (
select node_id, coalesce(parent_node_id, node_id), short_name, 1
from nodes_tab
union all
select cte.node_id, nt.parent_node_id, nt.short_name, lev + 1
from cte join
nodes_tab nt
on cte.parent_id = nt.node_id
)
select *
from (select cte.*, row_number() over (partition by node_id order by lev desc) as seqnum
from cte
) cte
where seqnum = 1;
Здесь — это рабочий пример db<>.
Oracle поддерживает рекурсивный факторинг подзапросов (который вы называете рекурсивным CTE), начиная с версии 11g Release 2, выпущенной в сентябре 2009 года. Уже почти 10 лет.
Вы ищете
CONNECT_BY_ROOT(short_name)? См. этот вопрос: stackoverflow.com/questions/15595850/…