Oracle 树上的逻辑

Posted

技术标签:

【中文标题】Oracle 树上的逻辑【英文标题】:Logic on Oracle Tree 【发布时间】:2021-11-18 23:02:29 【问题描述】:

下面是表格的结构:

REF_ID NOT NULL NUMBER REF_TYPE_ID NOT NULL NUMBER PARENT_REF_ID NUMBER REF_VALUE NOT NULL VARCHAR2(255)

以下查询已达到以下结果,但我可能需要结果:

WITH
    refs (ref_id,
          ref_type_id,
          parent_ref_id,
          ref_value)
    AS
        (SELECT 501, 1, NULL, 207 FROM DUAL
         UNION ALL
         SELECT 502, 2, 501, 4 FROM DUAL
         UNION ALL
         SELECT 503, 3, 502, 1 FROM DUAL)
    SELECT CONNECT_BY_ROOT r.ref_id as starting_ref_id,
           TRIM (
               ',' FROM
                   SYS_CONNECT_BY_PATH (
                          CASE r.ref_type_id
                              WHEN 1 THEN 'article '
                              WHEN 2 THEN 'par '
                              WHEN 3 THEN '('
                              WHEN 4 THEN 'point '
                              WHEN 5 THEN 'sous '
                              WHEN 6 THEN NULL
                              WHEN 8 THEN NULL
                              ELSE '/'
                          END
                       || r.ref_id,
                       ','))    AS ref_label
      FROM refs r
     WHERE CONNECT_BY_ISLEAF = 1
CONNECT BY PRIOR r.parent_ref_id = r.ref_id;

查询的输出:

STARTING_REF_ID REF_LABEL


           501 article 501
           502 par 502,article 501
           503 (503,par 502,article 501

预期结果:

STARTING_REF_ID REF_LABEL


           501 article 501
           502 article 501,par 502
           503 article 501,par 502,(503,

【问题讨论】:

【参考方案1】:

为选择添加反向

WITH
refs (ref_id,
      ref_type_id,
      parent_ref_id,
      ref_value)
AS
    (SELECT 501, 1, NULL, 207 FROM DUAL
     UNION ALL
     SELECT 502, 2, 501, 4 FROM DUAL
     UNION ALL
     SELECT 503, 3, 502, 1 FROM DUAL)
SELECT CONNECT_BY_ROOT r.ref_id as starting_ref_id,
       TRIM (
           ',' FROM
           reverse( --reverse path order (also reverts letters in words)
               SYS_CONNECT_BY_PATH (
                 
                     reverse( --put letters in words and numbers in ids back in the right order
                          CASE r.ref_type_id
                          WHEN 1 THEN 'article '
                          WHEN 2 THEN 'par '
                          WHEN 3 THEN '('
                          WHEN 4 THEN 'point '
                          WHEN 5 THEN 'sous '
                          WHEN 6 THEN NULL
                          WHEN 8 THEN NULL
                          ELSE '/'
                      END
                   || r.ref_id),
                   ',')
                   
                   ) )   AS ref_label
  FROM refs r
 WHERE CONNECT_BY_ISLEAF = 1
CONNECT BY PRIOR r.parent_ref_id = r.ref_id

【讨论】:

该解决方案符合 OP 的要求。但它有两个问题。首先,reverse 没有记录(因此不受支持);这对于非关键应用程序是可以的,但不应在重要应用程序的生产中使用。其次,OP 的现有查询一开始就有缺陷——它不是从根开始并从那里向下遍历树,而是朝着相反的方向前进。这个答案在相同的有缺陷的解决方案中提供了一个额外的补丁,而不是修复整个事情的根本原因(修复查询本身)。【参考方案2】:

你做这一切的方式非常不自然。

您应该从根(父 ID 为 null)开始,然后从它“向下”,而不是相反。那么你不需要where 子句,你需要一个start with 子句; connect by 条件必须相反。那么您不需要对查询进行任何其他更改。

像这样:

WITH
    refs (ref_id,
          ref_type_id,
          parent_ref_id,
          ref_value)
    AS
        (SELECT 501, 1, NULL, 207 FROM DUAL
         UNION ALL
         SELECT 502, 2, 501, 4 FROM DUAL
         UNION ALL
         SELECT 503, 3, 502, 1 FROM DUAL)
    SELECT CONNECT_BY_ROOT r.ref_id as starting_ref_id,
           TRIM (
               ',' FROM
                   SYS_CONNECT_BY_PATH (
                          CASE r.ref_type_id
                              WHEN 1 THEN 'article '
                              WHEN 2 THEN 'par '
                              WHEN 3 THEN '('
                              WHEN 4 THEN 'point '
                              WHEN 5 THEN 'sous '
                              WHEN 6 THEN NULL
                              WHEN 8 THEN NULL
                              ELSE '/'
                          END
                       || r.ref_id,
                       ','))    AS ref_label
      FROM refs r
START WITH parent_ref_id is null
CONNECT BY PRIOR ref_id = parent_ref_id;

【讨论】:

以上是关于Oracle 树上的逻辑的主要内容,如果未能解决你的问题,请参考以下文章

oracle体系结构-逻辑存储结构

关于IMP EXP逻辑备份oracle

Oracle存储(物理+逻辑)结构

Oracle体系结构概述

Oracle体系结构概述

oracle逻辑存储结构