Найти тему
Oracle APEX

Oracle. Иерархический каталог продуктов с подавлением пустых рубрик

Есть иерархический каталог групп товаров, но не во всех группах товар присутствует. Надо исключить из совокупного дерева ветви, на которых нет листьев-товаров. Решим на примере библиотеки.

В предыдущей заметке мы решили задачу, показав полный каталог:

Решение с демонстрацией полного каталога
Решение с демонстрацией полного каталога

Теперь нам необходимо его ограничить, подавив вывод пустых рубрик:

Постановка решения с подавлением пустых рубрик
Постановка решения с подавлением пустых рубрик

Начнем с определения множества рубрик, на которые есть публикации:

select topic_id from digest.lib_list_vi where type = :P7_TYPE
;

Если бы у нас была не иерархия, а плоская таблица, мы бы использовали конструкцию IN:

select... from... where id in
(select topic_id from digest.lib_list_vi where type = :P7_TYPE)
;

Но у нас иерархия и нам необходимо определить необходимые ветви в обратном направлении - не от корней к листьям, как обычно, а от нужных листьев к их корням. Соответственно, наше только что определенное множество встанет не в конструкцию IN, а в конструкцию START WITH запроса. Кроме этого, поскольку мы выполняем обратный траверс иерархии, в конструкции CONNECT BY отношение иерархического предшествования инвертируется: вместо традиционного connect by prior id = parent_id будет connect by prior parent_id = id, рождение пошло вспять от детей к родителям:

select * from digest.lib_topics_vi
start with id in (select topic_id from digest.lib_list_vi where type = :P7_TYPE)
connect by prior parent_id = id
;

Далее мы просто заменяем в каталожной части объединенного синтетического иерархического множества с составными ключами таблицу каталога на только что полученное выражение:

Было в предыдущей заметке:

select id, parent_id, text
from
(
select 'A'||id as id, 'A'||parent_id as parent_id, text, 'fa-folders' as icon
from digest.lib_topics_vi
union all
select 'B'||id, 'A'||topic_id, year||' - '||rtrim(authors, '. ')||nvl2(authors, '. ', null)||title, 'fa-book' as icon from digest.lib_list_vi where type = :P7_TYPE
)
start with parent_id = 'A'
connect by prior id = parent_id
order siblings by text
;

Стало:

select id, parent_id, text
from
(
select 'A'||id as id, 'A'||parent_id as parent_id, text, 'fa-folders' as icon
from
(
select * from digest.lib_topics_vi
start with id in (select topic_id from digest.lib_list_vi where type = :P7_TYPE)
connect by prior parent_id = id

)

union all
select 'B'||id, 'A'||topic_id, year||' - '||rtrim(authors, '. ')||nvl2(authors, '. ', null)||title, 'fa-book' as icon from digest.lib_list_vi where type = :P7_TYPE
)
start with parent_id = 'A'
connect by prior id = parent_id
order siblings by text
;

Задача решена:

Решение с подавлением пустых рубрик
Решение с подавлением пустых рубрик

Встроенный механизм иерархических запросов Oracle является мощным средством компактного решения нетривиальных задач. Oracle APEX позволяет на основе этих решений получить промышленный Web продукт с очень высокой скоростью разработки и доведения от прототипа до коммерческого результата.