简体   繁体   English

如何获取子记录的父母、祖父母等及其本身以及 SQL 中与根的距离

[英]How can i get a child record's parent, grandparent, and so on and itself along with the distance from root in SQL

I have a table as shown below -我有一张如下所示的表格 -

    ID | NAME        | PARENT

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

The column parent refers to the column id ie, Global is the root.父列是指列 id,即 Global 是根。 For USA-11, USA-1 is the parent, USA is the grandparent and Global is the great grand parent.对于 USA-11,USA-1 是父母,USA 是祖父母,Global 是曾祖父母。 It is a rugged hierarchy and can go upto any level .它是一个坚固的层次结构,可以 go 达到任何级别 I need help in writing a query that will expand this hierarchy in the following manner -我需要帮助编写一个查询,该查询将以下列方式扩展此层次结构 -

    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

So if you notice, I'm repeating every location name against itself and its hierarchy.因此,如果您注意到,我将针对其自身及其层次结构重复每个位置名称。 The column "distance_from_parent" is the distance from the parent mentioned in the "Parent" column. “distance_from_parent”列是与“Parent”列中提到的父级的距离。

I have tried this using Connect By, Level and prior, but unable to achieve this kind of output.我已经尝试过使用 Connect By、Level 和之前的方法,但无法实现这种 output。

The DDL for this is -用于此的 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);

Use a hierarchical query with CONNECT_BY_ROOT :使用带有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;

So for your test data:因此,对于您的测试数据:

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;

This outputs:这输出:

 ID |身份证 | NAME |姓名 | PARENT |家长 | DISTANCE_FROM_PARENT -: |:----- |:----- | DISTANCE_FROM_PARENT -: |:----- |:----- | -------------------: 1 | -------------------: 1 | Global |全球 | Global |全球 | 0 2 | 0 2 | USA |美国 | USA |美国 | 0 2 | 0 2 | USA |美国 | Global |全球 | 1 3 | 1 3 | Canada |加拿大 | Canada |加拿大 | 0 3 | 0 3 | Canada |加拿大 | Global |全球 | 1 4 | 1 4 | USA-1 |美国-1 | USA-1 |美国-1 | 0 4 | 0 4 | USA-1 |美国-1 | USA |美国 | 1 4 | 1 4 | USA-1 |美国-1 | Global |全球 | 2 5 | 2 5 | USA-11 |美国-11 | USA-11 |美国-11 | 0 5 | 0 5 | USA-11 |美国-11 | USA-1 |美国-1 | 1 5 | 1 5 | USA-11 |美国-11 | USA |美国 | 2 5 | 2 5 | USA-11 |美国-11 | Global |全球 | 3 3

db<>fiddle here db<> 在这里摆弄

You can use CONNECT BY to get your desired results:您可以使用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;

Here is a SQLFiddle with this solution.这是此解决方案的 SQLFiddle。 ( Link ) 链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM