Иерархический запрос для отображения всех дочерних элементов под каждым родителем - PullRequest
0 голосов
/ 02 марта 2019

Пожалуйста, смотрите прикрепленные изображения:

Визуальная диаграмма дерева

Visual diagram of hirarchy

ЖелаемыйВывод запроса

Desired query output

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

Ниже приведен код, который я пробовал (результаты не такие, как я ищу):

 SELECT parent,
        LEVEL,
        child

FROM  table1 

CONNECT BY NOCYCLE parent = PRIOR child;

1 Ответ

0 голосов
/ 02 марта 2019

Я изменил имена столбцов в вашей таблице с «CHILD» и «PARENT» на «ID» и «PARENT_ID», соответственно, чтобы быть немного менее запутанным.

В любом случае, вам нужно использовать CONNECT_BY_ROOT(parent_id), чтобы получить то, что отображается как «РОДИТЕЛЬ» в желаемом выходе.Если вам не важен порядок строк в вашем результате, это просто:

SELECT connect_by_root(parent_id) "PARENT", id "CHILD"
FROM   table1
WHERE  connect_by_root(parent_id) is not null
CONNECT BY parent_id = prior id

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

with hier as ( 
SELECT connect_by_root(parent_id) root_id, id, level, 
       case when connect_by_root(parent_id) is null then level else null end root_depth
FROM   table1
CONNECT BY parent_id = prior id
)
select h1.root_id "PARENT", h1.id "CHILD"
from hier h1 inner join hier h2 on h2.root_id is null and h2.id = h1.root_id
order by h2.root_depth, h1.root_id, h1.id

Вот полный пример с данными испытаний:

WITH table1 ( id, parent_id ) AS
( SELECT 'A', null FROM DUAL UNION ALL
  SELECT 'A1', 'A' FROM DUAL UNION ALL
  SELECT 'A2', 'A' FROM DUAL UNION ALL
  SELECT 'A3', 'A' FROM DUAL UNION ALL
  SELECT 'A11', 'A1' FROM DUAL UNION ALL
  SELECT 'A12', 'A1' FROM DUAL UNION ALL
  SELECT 'A21', 'A2' FROM DUAL UNION ALL
  SELECT 'A121', 'A12' FROM DUAL UNION ALL
  SELECT 'A122', 'A12' FROM DUAL ),
-- Solution begins here 
hier as ( 
SELECT connect_by_root(parent_id) root_id, id, level lvl, 
       case when connect_by_root(parent_id) is null then level else null end root_depth
FROM   table1
CONNECT BY parent_id = prior id
)
select h1.root_id "PARENT", h1.id "CHILD", h2.*
from hier h1 inner join hier h2 on h2.root_id is null and h2.id = h1.root_id
order by h2.root_depth, h1.root_id, h1.lvl, h1.id
+--------+-------+
| PARENT | CHILD |
+--------+-------+
| A      | A1    |
| A      | A2    |
| A      | A3    |
| A      | A11   |
| A      | A12   |
| A      | A21   |
| A      | A121  |
| A      | A122  |
| A1     | A11   |
| A1     | A12   |
| A1     | A121  |
| A1     | A122  |
| A2     | A21   |
| A12    | A121  |
| A12    | A122  |
+--------+-------+
...