如果缺少 1 级,则获取超级父级列表或显示父级

Fetch Super-parent list or show parent if 1 level is absent

我在 oracle 11G 中有一个 table 作为 -

ID  NAME        TYPE    DESCRIPTION PARENTID
1   INDIA       1       COUNTRY 
2   ZONE_A      2       REGION      1
3   ZONE_B      2       REGION      1
4   ZONE_C      2       REGION      1
5   CITY_1      3       CITY        2
6   CITY_2      3       CITY        2
7   CITY_3      3       CITY        3
8   CITY_4      3       CITY        3
9   BRANCH_1    4       BRANCH      5
10  BRANCH_2    4       BRANCH      5
11  BRANCH_3    4       BRANCH      6
12  BRANCH_4    4       BRANCH      6
13  BRANCH_5    4       BRANCH      3

正如您在此处看到的那样,分支机构将城市作为其父级,但有时它们可​​能没有任何城市作为其父级,而是直接将地区作为其父级。

我需要显示分支所属的区域。我创建了查询以将超级父区域显示为 -

SELECT C1.NAME, C3.NAME
FROM CTE C1
JOIN CTE C2 ON C1.PARENTID = C2.ID
JOIN CTE C3 ON C2.PARENTID = C3.ID
WHERE C1.DESCRIPTION = 'BRANCH';

这给了我正确的区域,但弄乱了没有任何父级的分支,即城市的任何行。

BRANCHES    PARENT  SUPER_PARENT
BRANCH_5    ZONE_B  INDIA
BRANCH_3    CITY_2  ZONE_A
BRANCH_4    CITY_2  ZONE_A
BRANCH_1    CITY_1  ZONE_A
BRANCH_2    CITY_1  ZONE_A

预期输出

如何在 SUPER_PARENT 列下显示 ZONE_B,因为这是仅显示具有正确区域的分支机构的要求。

BRANCHES    SUPER_PARENT
BRANCH_5    ZONE_B
BRANCH_3    ZONE_A
BRANCH_4    ZONE_A
BRANCH_1    ZONE_A
BRANCH_2    ZONE_A

Here 是 fiddle 供您参考。

对于您的示例数据和描述,以下returns区域名称:

SELECT B.NAME as BRANCH,
       COALESCE(BP2.NAME, BP.NAME) as REGION_NAME
FROM CTE B LEFT JOIN
     CTE BP
     ON B.PARENTID = BP.ID LEFT JOIN
     CTE BP2
     ON BP.PARENTID = BP2.ID AND BP2.DESCRIPTION = 'REGION'
WHERE B.DESCRIPTION = 'BRANCH';

您可以在通过大小写连接时检查连接上的类型是否是直接的前一个父级,如果不是像区域分支不是并发的,那么将这 2 列与其他父级同名

      SELECT C1.NAME, Case 
            when C1.Type-1 != 
       C2.Type THEN C1.NAME 
       ELSE C3.NAME END
    FROM CTE C1
   JOIN CTE C2 ON C1.PARENTID = C2.ID
  JOIN CTE C3 ON C2.PARENTID = C3.ID
    WHERE C1.DESCRIPTION = 'BRANCH';

您可以使用分层查询(不需要连接)更有效地完成此操作:

Oracle 设置:

CREATE TABLE table_name ( ID, NAME, TYPE, DESCRIPTION, PARENTID ) AS
  SELECT 1,  'INDIA',    1, 'COUNTRY', NULL FROM DUAL UNION ALL
  SELECT 2,  'ZONE_A',   2, 'REGION',  1 FROM DUAL UNION ALL
  SELECT 3,  'ZONE_B',   2, 'REGION',  1 FROM DUAL UNION ALL
  SELECT 4,  'ZONE_C',   2, 'REGION',  1 FROM DUAL UNION ALL
  SELECT 5,  'CITY_1',   3, 'CITY',    2 FROM DUAL UNION ALL
  SELECT 6,  'CITY_2',   3, 'CITY',    2 FROM DUAL UNION ALL
  SELECT 7,  'CITY_3',   3, 'CITY',    3 FROM DUAL UNION ALL
  SELECT 8,  'CITY_4',   3, 'CITY',    3 FROM DUAL UNION ALL
  SELECT 9,  'BRANCH_1', 4, 'BRANCH',  5 FROM DUAL UNION ALL
  SELECT 10, 'BRANCH_2', 4, 'BRANCH',  5 FROM DUAL UNION ALL
  SELECT 11, 'BRANCH_3', 4, 'BRANCH',  6 FROM DUAL UNION ALL
  SELECT 12, 'BRANCH_4', 4, 'BRANCH',  6 FROM DUAL UNION ALL
  SELECT 13, 'BRANCH_5', 4, 'BRANCH',  3 FROM DUAL;

查询:

SELECT CONNECT_BY_ROOT( name ) AS branch,
       PRIOR name AS parent,
       name AS super_parent
FROM   table_name
WHERE LEVEL = 3
START WITH description = 'BRANCH'
CONNECT BY id = PRIOR parentid

输出:

BRANCH   | PARENT | SUPER_PARENT
:------- | :----- | :-----------
BRANCH_1 | CITY_1 | ZONE_A      
BRANCH_2 | CITY_1 | ZONE_A      
BRANCH_3 | CITY_2 | ZONE_A      
BRANCH_4 | CITY_2 | ZONE_A      
BRANCH_5 | ZONE_B | INDIA       

db<>fiddle here

查询 2:

如果您只想要关联的区域:

SELECT CONNECT_BY_ROOT( name ) AS branch,
       name AS super_parent
FROM   table_name
WHERE  description     = 'REGION'
START WITH description = 'BRANCH'
CONNECT BY id = PRIOR parentid

输出:

BRANCH   | SUPER_PARENT
:------- | :-----------
BRANCH_1 | ZONE_A      
BRANCH_2 | ZONE_A      
BRANCH_3 | ZONE_A      
BRANCH_4 | ZONE_A      
BRANCH_5 | ZONE_B      

db<>fiddle here