Как я могу получить родителя, бабушки и дедушки и т. Д. И запись о себе, а также расстояние от root в SQL - PullRequest
0 голосов
/ 09 апреля 2020

У меня есть таблица, как показано ниже -

    ID | NAME        | PARENT

     1 | Global      | null 
     2 | USA         | 1
     3 | Canada      | 1
     4 | USA-1       | 2
     5 | USA-11      | 4

Родитель столбца относится к идентификатору столбца, т. Е. Global является root. Для США-11 США-1 - родитель, США - прародитель, а Глобал - пра-прародитель. Это грубая иерархия, которая может go подниматься до любого уровня . Мне нужна помощь в написании запроса, который расширит эту иерархию следующим образом -

    ID | NAME        | PARENT    | Distance_from_parent

     1 | Global      | Global    | 0
     2 | USA         | USA       | 0
     2 | USA         | Global    | 1
     3 | Canada      | Canada    | 0
     3 | Canada      | Global    | 1
     4 | USA-1       | USA-1     | 0
     4 | USA-1       | USA       | 1
     4 | USA-1       | Global    | 2
     5 | USA-11      | USA-11    | 0
     5 | USA-11      | USA-1     | 1
     5 | USA-11      | USA       | 2
     5 | USA-11      | Global    | 3

Так что, если вы заметили, я повторяю каждое имя местоположения относительно себя и его иерархии. Столбец «distance_from_parent» - это расстояние от родителя, упомянутого в столбце «Parent».

Я пробовал это использовать Connect By, Level и ранее, но не смог достичь такого вида вывода.

DDL для этого -

create table subsidiary (id number, name varchar2(50), parent number); 

insert into subsidiary (id, name, parent) values (1, 'Parent', null);
insert into subsidiary (id, name, parent) values (2, 'USA', 1);
insert into subsidiary (id, name, parent) values (3, 'Canada', 1);
insert into subsidiary (id, name, parent) values (4, 'USA-1', 2);
insert into subsidiary (id, name, parent) values (5, 'USA-11', 4);

Ответы [ 2 ]

1 голос
/ 09 апреля 2020

Используйте иерархический запрос с CONNECT_BY_ROOT:

SELECT CONNECT_BY_ROOT( ID ) AS id,
       CONNECT_BY_ROOT( name ) AS name,
       name AS parent,
       LEVEL - 1 AS distance_from_parent
FROM   subsidiary
CONNECT BY PRIOR parent = id
ORDER BY id, distance_from_parent;

Так что для ваших тестовых данных:

CREATE TABLE subsidiary ( ID, NAME, PARENT ) AS
SELECT 1, 'Global', null FROM DUAL UNION ALL 
SELECT 2, 'USA',    1 FROM DUAL UNION ALL
SELECT 3, 'Canada', 1 FROM DUAL UNION ALL
SELECT 4, 'USA-1',  2 FROM DUAL UNION ALL
SELECT 5, 'USA-11', 4 FROM DUAL;

Это выводит:

ID | NAME   | PARENT | DISTANCE_FROM_PARENT
-: | :----- | :----- | -------------------:
 1 | Global | Global |                    0
 2 | USA    | USA    |                    0
 2 | USA    | Global |                    1
 3 | Canada | Canada |                    0
 3 | Canada | Global |                    1
 4 | USA-1  | USA-1  |                    0
 4 | USA-1  | USA    |                    1
 4 | USA-1  | Global |                    2
 5 | USA-11 | USA-11 |                    0
 5 | USA-11 | USA-1  |                    1
 5 | USA-11 | USA    |                    2
 5 | USA-11 | Global |                    3

дБ <> скрипка здесь

0 голосов
/ 09 апреля 2020

Вы можете использовать CONNECT BY для получения желаемых результатов:

SELECT s.id, s.name, CONNECT_BY_ROOT(s.name) AS ROOT_NAME, LEVEL-1 AS ROOT_DISTANCE
FROM subsidiary s
CONNECT BY s.parent = PRIOR(s.id)
ORDER BY s.id, LEVEL;

Вот SQLFiddle с этим решением. ( Link )

...