Получить все подконтуры в иерархическом запросе в Oracle

голоса
0

У меня есть таблица, которая содержит список отделов продаж следующим образом:

+-------+---------------+-----------+
|DEPT_ID|DEPT_NAME      |DEPT_PARENT|
+-------+---------------+-----------+
|5500   |World          |           |
|5510   |Region 1       |5500       |
|5511   |Cell 1 Region 1|5510       |
|5512   |Cell 2 Region 1|5510       |
|5513   |Cell 3 Region 1|5510       |
|5514   |Cell 4 Region 1|5510       |
|5515   |Cell 5 Region 1|5510       |
|5520   |Region 2       |5500       |
|5521   |Cell 1 Region 2|5520       |
|5522   |Cell 2 Region 2|5520       |
|5530   |Region 3       |5500       |
|5531   |Cell 1 Region 3|5530       |
|5532   |Cell 2 Region 3|5530       |
|5540   |Region 4       |5500       |
|5533   |Cell 1 Region 4|5540       |
|5534   |Cell 2 Region 4|5533       |
|5590   |Region 5       |5500       |
|5591   |Cell 1 Region 5|5590       |
+-------+---------------+-----------+

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

5500 5510
5500 5511
5510 5511

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

    SELECT d.*, LTRIM (SYS_CONNECT_BY_PATH (dept_id, '-'), '-') AS PATH
      FROM depts d
START WITH dept_parent IS NULL
CONNECT BY PRIOR dept_id = dept_parent

но как я могу получить все возможные подконтуры?

Задан 13/01/2020 в 21:56
источник пользователем
На других языках...                            


2 ответов

голоса
0

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

Вот решение, которое использует стандартный рекурсивный запрос для достижения этой цели. Я также добавил столбец, который сохраняет глубину отношений, так как эта информация часто используется в таблицах закрытия.

with cte(node_id, dept_id, dept_parent, lvl) as (
    select dept_id node_id, dept_id, dept_parent, 0 lvl from dept
    union all 
    select c.node_id, d.dept_id, d.dept_parent, c.lvl + 1
    from cte c
    inner join dept d on d.dept_id = c.dept_parent
)
select dept_id ancestor, node_id node, lvl 
from cte 
where lvl > 0
order by node, ancestor

Это демо на DB Fiddle с образцами данных производит 30 строк, у которых первых 10 являются:

ПРЕДОК | УЗЕЛ | LVL
-------: | ---: | -:
    5500 | 5510 | 1
    5500 | 5511 | 2
    5510 | 5511 | 1
    5500 | 5512 | 2
    5510 | 5512 | 1
    5500 | 5513 | 2
    5510 | 5513 | 1
    5500 | 5514 | 2
    5510 | 5514 | 1
    5500 | 5515 | 2
Ответил 13/01/2020 в 22:39
источник пользователем

голоса
1

Используйте , CONNECT_BY_ROOTчтобы найти начало пути.

Настройка Oracle :

CREATE TABLE depts ( DEPT_ID, DEPT_NAME, DEPT_PARENT ) AS
SELECT 5500, 'World',           NULL FROM DUAL UNION ALL
SELECT 5510, 'Region 1',        5500 FROM DUAL UNION ALL
SELECT 5511, 'Cell 1 Region 1', 5510 FROM DUAL UNION ALL
SELECT 5512, 'Cell 2 Region 1', 5510 FROM DUAL UNION ALL
SELECT 5513, 'Cell 3 Region 1', 5510 FROM DUAL UNION ALL
SELECT 5514, 'Cell 4 Region 1', 5510 FROM DUAL UNION ALL
SELECT 5515, 'Cell 5 Region 1', 5510 FROM DUAL UNION ALL
SELECT 5520, 'Region 2',        5500 FROM DUAL UNION ALL
SELECT 5521, 'Cell 1 Region 2', 5520 FROM DUAL UNION ALL
SELECT 5522, 'Cell 2 Region 2', 5520 FROM DUAL UNION ALL
SELECT 5530, 'Region 3',        5500 FROM DUAL UNION ALL
SELECT 5531, 'Cell 1 Region 3', 5530 FROM DUAL UNION ALL
SELECT 5532, 'Cell 2 Region 3', 5530 FROM DUAL UNION ALL
SELECT 5540, 'Region 4',        5500 FROM DUAL UNION ALL
SELECT 5533, 'Cell 1 Region 4', 5540 FROM DUAL UNION ALL
SELECT 5534, 'Cell 2 Region 4', 5533 FROM DUAL UNION ALL
SELECT 5590, 'Region 5',        5500 FROM DUAL UNION ALL
SELECT 5591, 'Cell 1 Region 5', 5590 FROM DUAL;

Запрос :

SELECT CONNECT_BY_ROOT( dept_parent ) AS ancestor,
       dept_id,
       SYS_CONNECT_BY_PATH( dept_parent, '>' ) || '>' || dept_id AS path
FROM   depts
START WITH dept_parent IS NOT NULL
CONNECT BY PRIOR dept_id = dept_parent;

Выход :

ПРЕДОК | dept_id | ПУТЬ                
-------: | ------: | : -------------------
    5500 | 5510 | > 5500> 5510          
    5500 | 5511 | > 5500> 5510> 5511     
    5500 | 5512 | > 5500> 5510> 5512     
    5500 | 5513 | > 5500> 5510> 5513     
    5500 | 5514 | > 5500> 5510> 5514     
    5500 | 5515 | > 5500> 5510> 5515     
    5500 | 5520 | > 5500> 5520          
    5500 | 5521 | > 5500> 5520> 5521     
    5500 | 5522 | > 5500> 5520> 5522     
    5500 | 5530 | > 5500> 5530          
    5500 | 5531 | > 5500> 5530> 5531     
    5500 | 5532 | > 5500> 5530> 5532     
    5500 | 5540 | > 5500> 5540          
    5500 | 5533 | > 5500> 5540> 5533     
    5500 | 5534 | > 5500> 5540> 5533> 5534
    5500 | 5590 | > 5500> 5590          
    5500 | 5591 | > 5500> 5590> 5591     
    5510 | 5511 | > 5510> 5511          
    5510 | 5512 | > 5510> 5512          
    5510 | 5513 | > 5510> 5513          
    5510 | 5514 | > 5510> 5514          
    5510 | 5515 | > 5510> 5515          
    5520 | 5521 | > 5520> 5521          
    5520 | 5522 | > 5520> 5522          
    5530 | 5531 | > 5530> 5531          
    5530 | 5532 | > 5530> 5532          
    5533 | 5534 | > 5533> 5534          
    5540 | 5533 | > 5540> 5533          
    5540 | 5534 | > 5540> 5533> 5534     
    5590 | 5591 | > 5590> 5591          

дб <> скрипку здесь

Ответил 13/01/2020 в 22:50
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more