powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Работа с иерархиями: удалить из иерархии всех дочек удаленной на предыдущем шаге ноды.
14 сообщений из 14, страница 1 из 1
Работа с иерархиями: удалить из иерархии всех дочек удаленной на предыдущем шаге ноды.
    #40099970
lav314
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
/* Работаю с Hana, но хотелось бы решения на стандартном SQL, поэтому обращаюсь к форуму Oracle. */

Дано:

Есть (сохранена в таблице tab_hyer) уже построенная иерархия с колонками

rank, tree_size, parent_id, node_id, delete_flag

где
rank - номер текущей ноды (данное дерево упорядочено по rank от 1 до некоего максимального значения)
tree_size - размер под-дерева, исходящего из этого узла, то есть число всех дочерних нод первого порядка, их ноды, ноды этих нод и так далее до листьев. То есть если взять строку с rank = 4 и в ней будет стоять tree_size = 234, строки с ранками между 4+1 .... 4+234 будут всеми дочерними нодами всех порядов строки с rank = 4.
delete_flag - выставленный сторонним алгоритмом флаг, который говорит, что некоторые ноды дерева на самом деле ошибочные и должны быть удалены (такие ноды помечены delete_flag = true, остальные помечены false)

Для простоты предположить, что в иерархии одно дерево с одним корнем (rank = 1).
В дереве соотношение одни ко многим, то есть из parent может выходить несколько node, но у каждой node строго один parent.


Задача:
написать update поля delete_flag таблицы tab_hyer, который для всех дочек всех строк с delete_flag = true проставит delete_flag = true, то есть: если сторонний алгоритм пометил ноду как ошибочную, нужно пометить и всё исходящее из нее под-дерево на удаление.

Можно, но не хотелось бы, вместо update текущей таблицы создать новую таблицу с результатом апдейта.


Ограничения:
Можно использовать джойны, оконные функции, нельзя использовать pl/sql, циклы и встроенные функции работы с иерархиями типа "верну все ранки всех нод, исходящих из данной ноды, только скажи мне ее ранк".

Опционно:
вместо решения сообщить мне куда пройти, что решение, даже если оно существует, будет нечитабельно и неподдерживаемо в силу своей интеллектуальной изощренности и посоветовать отказаться от ограничений.
...
Рейтинг: 0 / 0
Работа с иерархиями: удалить из иерархии всех дочек удаленной на предыдущем шаге ноды.
    #40099998
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
lav314
на стандартном SQL
нельзя использовать … встроенные функции работы с иерархиями типа "верну все ранки всех нод, исходящих из данной ноды, только скажи мне ее ранк"

куда пройти
И зачем ты тогда пришёл в Oracle?
...
Рейтинг: 0 / 0
Работа с иерархиями: удалить из иерархии всех дочек удаленной на предыдущем шаге ноды.
    #40100017
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
lav314
То есть если взять строку с rank = 4 и в ней будет стоять tree_size = 234, строки с ранками между 4+1 .... 4+234 будут всеми дочерними нодами всех порядов строки с rank = 4.


Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
update tab_hyer
   set delete_flag = 'true'
 where rank in (
                select  rank + offset
                  from  tab_hyer,
                        lateral(
                                select  level offset
                                  from  dual
                                  connect by level <= tree_size
                               )
                  where delete_flag = 'true'
               )
/



SY.
P.S. LATERAL можно заменить на CROSS APPLY.
...
Рейтинг: 0 / 0
Работа с иерархиями: удалить из иерархии всех дочек удаленной на предыдущем шаге ноды.
    #40100018
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SY
Код: plsql
1.
connect by level

lav314
нельзя использовать … встроенные функции работы с иерархиями типа "верну все ранки всех нод, исходящих из данной ноды, только скажи мне ее ранк"
...
Рейтинг: 0 / 0
Работа с иерархиями: удалить из иерархии всех дочек удаленной на предыдущем шаге ноды.
    #40100020
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
update tab_hyer h1
  set delete_flag = 'true'
  where delete_flag = 'false'
    and exists (select null from tab_hyer h2 where h1.rank between h2.rank + 1 and h2.rank + h2.tree_size and h2.delete_flag = 'true')

...
Рейтинг: 0 / 0
Работа с иерархиями: удалить из иерархии всех дочек удаленной на предыдущем шаге ноды.
    #40100021
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Elic
SY
Код: plsql
1.
connect by level

lav314
нельзя использовать … встроенные функции работы с иерархиями типа "верну все ранки всех нод, исходящих из данной ноды, только скажи мне ее ранк"



Ну мультипликатор строк это не типа "верну все ранки всех нод, исходящих из данной ноды, только скажи мне ее ранк" и есть куча других мультипликаторов. Например:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
update tab_hyer
   set delete_flag = 'true'
 where rank in (
                select  rank + offset
                  from  tab_hyer,
                        lateral(
                                select  offset
                                  from  xmltable(
                                                 '1 to xs:integer(.)'
                                                 passing tree_size
                                                 columns
                                                   offset number path '.'
                                                )
                               )
                  where delete_flag = 'true'
               )
/



А можно и без мультипликатора строк:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
update tab_hyer
   set delete_flag = 'true'
 where rank in (
                with driver as (
                                select  rank + 1 rank_from,
                                        rank + tree_size rank_to
                                  from  tab_hyer
                                  where delete_flag = 'true'
                               )
                select  t.rank
                  from  tab_hyer t,
                        driver d
                  where t.rank between d.rank_from and d.rank_to
               )
/



SY.
...
Рейтинг: 0 / 0
Работа с иерархиями: удалить из иерархии всех дочек удаленной на предыдущем шаге ноды.
    #40100025
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SY
А можно и без мультипликатора строк:
Всё равно перемудрил.
...
Рейтинг: 0 / 0
Работа с иерархиями: удалить из иерархии всех дочек удаленной на предыдущем шаге ноды.
    #40100059
serpv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
а parent_id разве не надо в иерархии учитывать? казалось бы задача отметить потомков только нужных узлов.
...
Рейтинг: 0 / 0
Работа с иерархиями: удалить из иерархии всех дочек удаленной на предыдущем шаге ноды.
    #40100082
lav314
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
serpv
а parent_id разве не надо в иерархии учитывать? казалось бы задача отметить потомков только нужных узлов.


Иерархия уже построена - все строки специально занумерованы (те самые ранки). Отменить нужно не только ближайших потомков нужных узлов (в ближайшем потомке мы храним parent и ваша идея сработает), а вообще всех потомков этого узла, в моем случае может быть до десяти уровней глубины. А мы ведь храним только ближайшего parent в строке и не знаем, какой parent был на три (для примера) уровня выше.
...
Рейтинг: 0 / 0
Работа с иерархиями: удалить из иерархии всех дочек удаленной на предыдущем шаге ноды.
    #40100083
lav314
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Благодарю SY за решения через drivers и Elic за решение через exist (выглядит очень изящно!).

Буду разбираться с этими решениями. Надеюсь, они учитывают, что интервалы удаляемых нод могут быть включены один в другой и т.д., то есть сторонний алгоритм мог пометить ноду 345 и ноду 367 на удаление, но при этом 367-я - дочка N-того уровня 345-й, то есть она и все ее дочки будут и так удалены при удалении потомков 345-й. Я не против, если поддерево 367-й будет помечено на удаление два раза :-)
...
Рейтинг: 0 / 0
Работа с иерархиями: удалить из иерархии всех дочек удаленной на предыдущем шаге ноды.
    #40100086
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
lav314
Я не против, если поддерево 367-й будет помечено на удаление два раза
Так и говори, что ничего не понимаешь в SQL.
Elic
Код: plsql
1.
where delete_flag = 'false'

...
Рейтинг: 0 / 0
Работа с иерархиями: удалить из иерархии всех дочек удаленной на предыдущем шаге ноды.
    #40100140
lav314
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Так как я ничего не понимаю в SQL, прошу Elic рассмотреть следующую задачу

1) Есть изначальная таблица tab_hyer, заполненная простейшей иерархией ( 1<-- 2 <-- 3 <-- 4 )

Код: plsql
1.
2.
3.
4.
5.
6.
7.
сreate table tab_hyer as
select 1 as rank, 3 as tree_size, null as parent_id, 1 as node_id, false as delete_flag from dual union all -- это корневая нода
select 2, 2, 1, 2, false  from dual union all
select 3, 1, 2, 3, false  from dual union all
select 4, 0, 3, 4, false  from dual -- это единственный лист дерева
; 
commit;


2) Есть сторонний процесс, который пометил на удаление корневую и два нижележащих узла


Код: plsql
1.
2.
3.
4.
5.
6.
7.
update tab_hyer 
set
   delete_flag = true
where 
   rank in (1,2,3)
;
commit;



Таким образом теперь нода rank = 4 входит в три вложенных в друг друга поддерева, которые должны быть удалены.

3) Есть написанный Elic скрипт удаления дочерних нод всех уровней для удаленных ранее сторонним процессом узлов:

Код: plsql
1.
2.
3.
4.
update tab_hyer h1
  set delete_flag = 'true'
  where delete_flag = 'false'
    and exists (select null from tab_hyer h2 where h1.rank between h2.rank + 1 and h2.rank + h2.tree_size and h2.delete_flag = 'true')



4) Доказать (желательно средствами, доступными ничего не понимающему в sql человеку), что при исполнении скрипта из пункта 3 строка с rank = 4 будет проверена на условие
Код: plsql
1.
exists (select null from tab_hyer h2 where h1.rank between h2.rank + 1 and h2.rank + h2.tree_size and h2.delete_flag = 'true')


одни раз, а не три раза как предполагаю я.
...
Рейтинг: 0 / 0
Работа с иерархиями: удалить из иерархии всех дочек удаленной на предыдущем шаге ноды.
    #40100151
serpv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
lav314
В дереве соотношение одни ко многим, то есть из parent может выходить несколько node, но у каждой node строго один parent.
можете показать пример сreate table tab_hyer для этого случая, как заполняются rank, tree_size, parent_id, node_id в случае более чем одного листа в дереве?
...
Рейтинг: 0 / 0
Работа с иерархиями: удалить из иерархии всех дочек удаленной на предыдущем шаге ноды.
    #40100184
Michael Isaev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Elic
lav314
на стандартном SQL
нельзя использовать … встроенные функции работы с иерархиями типа "верну все ранки всех нод, исходящих из данной ноды, только скажи мне ее ранк"

куда пройти
И зачем ты тогда пришёл в Oracle?

Вот тоже хотел спросить, так как в HANA есть отличные от Oracle средства работы с иерархиями.
Кстати, пример топикстартер, таблица и столбцы очень похожи на те, что даются в документации HANA .
Что то мне кажется, что топикстартер - ленивый троль.
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Работа с иерархиями: удалить из иерархии всех дочек удаленной на предыдущем шаге ноды.
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]