【问题标题】:Display immediate parent after CONNECT_BY_ROOT in Oracle PL SQL在 Oracle PL SQL 中的 CONNECT_BY_ROOT 之后显示直接父级
【发布时间】:2020-11-07 04:01:49
【问题描述】:

我正在使用 oracle 12 DB 和客户端。在这方面需要帮助。我想填充一个在根之后显示根、子和直接父的列?让我们说“通过第二根连接”?

这是我目前的代码。

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, ....

在根之后获取父级,但它给了我一个 ORA-01489 错误。

请多多指教,提前致谢

【问题讨论】:

    标签: sql oracle connect-by


    【解决方案1】:

    您可以使用条件 sys_connect_by_path:

    rtrim(sys_connect_by_path(case when level<=2 then id else null end, '.'),'.') 
    

    【讨论】:

    • 嗨,Sayan,如果我尝试将 sys_connect_by_path 与 rtrim 或 substr 结合使用会出现 ORA-01489... 还尝试使用 TO_CLOB 来防止错误,但它一直出现
    • @user1215811 这很奇怪。请向我们展示您的数据样本
    • 嗨,Sayan,我更正了我之前的评论。只是运行了一个错误的 SQL,这就是 Ora-01489 出现的原因。是的,您的条件 sys_connect_by_path: 有效。这是我需要的。非常感谢。先生,感激不尽。
    【解决方案2】:

    这可以使用 LEVEL 关键字来解决。 LEVEL 显示每条记录在层次结构中相对于根的位置或级别。所以在经典的 EMPLOYEE 表中,如果员工 Jake 有这个层次结构:

    杰克 -> 杰克的经理 -> 副总裁 -> 首席执行官

    那么 Jake 在第 1 级,经理在第 2 级,副总裁在第 3 级,CEO 在第 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 的经理 -> VP 有记录.. 等等,所有这些记录都属于员工 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 列。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-02
      • 1970-01-01
      • 1970-01-01
      • 2018-08-09
      • 2019-08-03
      • 1970-01-01
      • 2019-08-21
      • 1970-01-01
      相关资源
      最近更新 更多