如果缺少 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
我在 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