在 Oracle PL SQL 中 CONNECT_BY_ROOT 之后显示直接父级
Display immediate parent after CONNECT_BY_ROOT in Oracle PL SQL
我正在使用 oracle 12 数据库和客户端。在这方面需要帮助。我想填充一个在根之后显示根、子和直接父的列?让我们说“通过第二根连接”?
到目前为止,这是我的代码。
SELECT
PARENT,
CONNECT_BY_ROOT PARENT_ID AS ROOT_ID,
????2ND_ROOT_ID,
CHILD_ID AS CHILD_ID
FROM TABLE
START WITH
PARENT_ID = 1
CONNECT BY
PRIOR CHILD_ID = PARENT_ID
输入
PARENT_ID CHILD_ID
1 1.1
1 1.2
1.1 1.1.1
1.1 1.1.2
1.1 1.1.3
1.1 1.1.4
1.1 1.1.5
1.2 1.2.1
1.2 1.2.2
1.1.1 1.1.1.1
1.1.1 1.1.1.2
1.1.3 1.1.3.1
1.1.3 1.1.3.2
1.1.3 1.1.3.3
输出:
ROOT_ID 2ND_ROOT_ID CHILD_ID
1 1.1 1.1
1 1.2 1.2
1 1.1 1.1.1
1 1.1 1.1.2
1 1.1 1.1.3
1 1.1 1.1.4
1 1.1 1.1.5
1 1.2 1.2.1
1 1.2 1.2.2
1 1.1 1.1.1.1
1 1.1 1.1.1.2
1 1.1 1.1.3.1
1 1.1 1.1.3.2
1 1.1 1.1.3.3
还尝试使用通过路径连接的子字符串
regexp_substr(SYS_CONNECT_BY_PATH, ....
要在 root 之后获取父级,但它会给我一个 ORA-01489 错误。
请提前多多指教
您可以使用条件 sys_connect_by_path:
rtrim(sys_connect_by_path(case when level<=2 then id else null end, '.'),'.')
这可以使用 LEVEL 关键字来解决。 LEVEL 显示每个记录在层次结构中相对于根的位置或级别。因此,在经典的 EMPLOYEE table 中,如果员工 Jake 具有以下层次结构:
杰克 -> 杰克的经理 -> 副总裁 -> 首席执行官
然后 Jake 在 LEVEL 1,Manager 在 LEVEL 2,VP 在 LEVEL 3,CEO 在 LEVEL 4。
您要的是简单地选择所有第 4、3 和 1 级记录,这将为您提供根、第二根和记录本身。但是有一个问题 - LEVEL 编号从底部开始,而不是从顶部开始。因此,您不知道给定员工的根处于什么级别。它可以是 2、3、4、5 或任何数字,具体取决于层次结构中的级别数。
在 Oracle 中,CONNECT_BY_ROOT 提供根记录,但获得第二个根并不简单。
这就是为什么下面的查询使用 ROW_NUMBER() 分析函数来恢复级别的顺序 以便根变为 LEVEL 1,第二个根变为 LEVEL 2 并且很快。如果 root 始终处于 LEVEL 1 并且 root 的直接子级始终处于 LEVEL 2,那么针对这两者编写 WHERE 子句就变得容易了。
当您像这样使用 CONNECT BY 时,每个关系都有一个单独的记录。在下面的 WITH 子句中,员工 Jake 拥有的记录数量与他拥有的上至 CEO 的经理数量一样多。所以 Jake -> Jake 的经理有记录。 Jake -> Jake's Manager->VP has a record.. 依此类推,所有属于员工 Jake 的记录。
下面的 EMP WITH 子句使用 ROW_NUMBER() 为每个从 1 开始的关系记录分配增量行号作为根。对于下一位员工,它再次从 1 开始。
EMP_PIVOT 通过使用上一步的 ROW_NUMBER() 计算旋转经理姓名来创建一个新列。
WITH EMP AS
(
SELECT E.employee_id, E.employee_name, E.designation,
CONNECT_BY_ROOT E.employee_name as Manager_name,
CONNECT_BY_ROOT E.designation as Manager_Designation,
LEVEL EMP_LEVEL,
ROW_NUMBER() OVER(PARTITION BY EMPLOYEE_ID ORDER BY LEVEL DESC) LEVEL_HIERARCHY
FROM Employee E
CONNECT BY PRIOR E.employee_id = E.manager_id
ORDER BY 1
),
EMP_PIVOT AS
(
SELECT
MAX(DECODE(EMP.LEVEL_HIERARCHY,1,EMP.MANAGER_NAME, NULL)) OVER(PARTITION BY EMPLOYEE_ID) AS ROOT_MGR,
EMP.MANAGER_NAME AS SECOND_ROOT_MGR,
EMP.EMPLOYEE_NAME,
LEVEL_HIERARCHY
FROM EMP
WHERE EMP.LEVEL_HIERARCHY <=2 )
SELECT * FROM EMP_PIVOT WHERE LEVEL_HIERARCHY=2;
输出:
最后一个 WHERE 条件设置为 LEVEL_HIERARCHY=2 因此我们只为每个员工获取一条记录,其中包含我们需要的所有 3 列。
我正在使用 oracle 12 数据库和客户端。在这方面需要帮助。我想填充一个在根之后显示根、子和直接父的列?让我们说“通过第二根连接”?
到目前为止,这是我的代码。
SELECT
PARENT,
CONNECT_BY_ROOT PARENT_ID AS ROOT_ID,
????2ND_ROOT_ID,
CHILD_ID AS CHILD_ID
FROM TABLE
START WITH
PARENT_ID = 1
CONNECT BY
PRIOR CHILD_ID = PARENT_ID
输入
PARENT_ID CHILD_ID
1 1.1
1 1.2
1.1 1.1.1
1.1 1.1.2
1.1 1.1.3
1.1 1.1.4
1.1 1.1.5
1.2 1.2.1
1.2 1.2.2
1.1.1 1.1.1.1
1.1.1 1.1.1.2
1.1.3 1.1.3.1
1.1.3 1.1.3.2
1.1.3 1.1.3.3
输出:
ROOT_ID 2ND_ROOT_ID CHILD_ID
1 1.1 1.1
1 1.2 1.2
1 1.1 1.1.1
1 1.1 1.1.2
1 1.1 1.1.3
1 1.1 1.1.4
1 1.1 1.1.5
1 1.2 1.2.1
1 1.2 1.2.2
1 1.1 1.1.1.1
1 1.1 1.1.1.2
1 1.1 1.1.3.1
1 1.1 1.1.3.2
1 1.1 1.1.3.3
还尝试使用通过路径连接的子字符串
regexp_substr(SYS_CONNECT_BY_PATH, ....
要在 root 之后获取父级,但它会给我一个 ORA-01489 错误。
请提前多多指教
您可以使用条件 sys_connect_by_path:
rtrim(sys_connect_by_path(case when level<=2 then id else null end, '.'),'.')
这可以使用 LEVEL 关键字来解决。 LEVEL 显示每个记录在层次结构中相对于根的位置或级别。因此,在经典的 EMPLOYEE table 中,如果员工 Jake 具有以下层次结构:
杰克 -> 杰克的经理 -> 副总裁 -> 首席执行官
然后 Jake 在 LEVEL 1,Manager 在 LEVEL 2,VP 在 LEVEL 3,CEO 在 LEVEL 4。
您要的是简单地选择所有第 4、3 和 1 级记录,这将为您提供根、第二根和记录本身。但是有一个问题 - LEVEL 编号从底部开始,而不是从顶部开始。因此,您不知道给定员工的根处于什么级别。它可以是 2、3、4、5 或任何数字,具体取决于层次结构中的级别数。
在 Oracle 中,CONNECT_BY_ROOT 提供根记录,但获得第二个根并不简单。
这就是为什么下面的查询使用 ROW_NUMBER() 分析函数来恢复级别的顺序 以便根变为 LEVEL 1,第二个根变为 LEVEL 2 并且很快。如果 root 始终处于 LEVEL 1 并且 root 的直接子级始终处于 LEVEL 2,那么针对这两者编写 WHERE 子句就变得容易了。
当您像这样使用 CONNECT BY 时,每个关系都有一个单独的记录。在下面的 WITH 子句中,员工 Jake 拥有的记录数量与他拥有的上至 CEO 的经理数量一样多。所以 Jake -> Jake 的经理有记录。 Jake -> Jake's Manager->VP has a record.. 依此类推,所有属于员工 Jake 的记录。
下面的 EMP WITH 子句使用 ROW_NUMBER() 为每个从 1 开始的关系记录分配增量行号作为根。对于下一位员工,它再次从 1 开始。
EMP_PIVOT 通过使用上一步的 ROW_NUMBER() 计算旋转经理姓名来创建一个新列。
WITH EMP AS
(
SELECT E.employee_id, E.employee_name, E.designation,
CONNECT_BY_ROOT E.employee_name as Manager_name,
CONNECT_BY_ROOT E.designation as Manager_Designation,
LEVEL EMP_LEVEL,
ROW_NUMBER() OVER(PARTITION BY EMPLOYEE_ID ORDER BY LEVEL DESC) LEVEL_HIERARCHY
FROM Employee E
CONNECT BY PRIOR E.employee_id = E.manager_id
ORDER BY 1
),
EMP_PIVOT AS
(
SELECT
MAX(DECODE(EMP.LEVEL_HIERARCHY,1,EMP.MANAGER_NAME, NULL)) OVER(PARTITION BY EMPLOYEE_ID) AS ROOT_MGR,
EMP.MANAGER_NAME AS SECOND_ROOT_MGR,
EMP.EMPLOYEE_NAME,
LEVEL_HIERARCHY
FROM EMP
WHERE EMP.LEVEL_HIERARCHY <=2 )
SELECT * FROM EMP_PIVOT WHERE LEVEL_HIERARCHY=2;
输出:
最后一个 WHERE 条件设置为 LEVEL_HIERARCHY=2 因此我们只为每个员工获取一条记录,其中包含我们需要的所有 3 列。