我如何获得 child 记录的 parent、grandparent 等及其本身以及与 SQL 中根的距离
How can i get a child record's parent, grandparent, and so on and itself along with the distance from root in SQL
我有一个table如下图-
ID | NAME | PARENT
1 | Global | null
2 | USA | 1
3 | Canada | 1
4 | USA-1 | 2
5 | USA-11 | 4
列 parent 指的是列 id,即 Global 是根。对于 USA-11,USA-1 是 parent,USA 是 grandparent,Global 是曾祖父 parent。 这是一个坚固的层次结构,可以上升到任何级别。
我需要帮助编写一个查询,该查询将按以下方式扩展此层次结构 -
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" 列中提到的 parent 的距离。
我尝试过使用 Connect By、Level 和 prior,但无法实现这种输出。
这个的 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);
您可以使用 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)
使用分层查询 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
db<>fiddle here
我有一个table如下图-
ID | NAME | PARENT
1 | Global | null
2 | USA | 1
3 | Canada | 1
4 | USA-1 | 2
5 | USA-11 | 4
列 parent 指的是列 id,即 Global 是根。对于 USA-11,USA-1 是 parent,USA 是 grandparent,Global 是曾祖父 parent。 这是一个坚固的层次结构,可以上升到任何级别。 我需要帮助编写一个查询,该查询将按以下方式扩展此层次结构 -
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" 列中提到的 parent 的距离。
我尝试过使用 Connect By、Level 和 prior,但无法实现这种输出。
这个的 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);
您可以使用 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)
使用分层查询 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
db<>fiddle here