在 Oracle 中使用先验垂直连接而不是水平连接获取路径层次结构?

Get path hierarhy using connect by prior vertical instead of horizontal in Oracle?

您好,我有一个使用 connect by prior 的 SQL 语句。我想通过特定的 where 标准获取路径。以下 SQL 工作正常,但我不想只获得符合条件的一行,我还想获得每个父记录(垂直向上层次结构)。

SELECT SUBSTR(SYS_CONNECT_BY_PATH(R.CALCULATION_PLAN_CODE, '.'),4) CODE_PATH,
       SUBSTR(SYS_CONNECT_BY_PATH(R.CALCULATION_PLAN_NAME, ' > '),29) NAME_PATH,           
       R.CALCULATION_PLAN_CODE,
       R.CALCULATION_PLAN_NAME        
  FROM PRM.MOVABLE_CALCULATION_PLAN R
  WHERE R.RELATED_YEAR = :relatedYear
  AND R.CALCULATION_PLAN_PARENT_OID != 0
  AND REGEXP_LIKE (R.CALCULATION_PLAN_NAME,'ROL')
  AND  CONNECT_BY_ISLEAF  = 1 
 START WITH R.OID =
          (SELECT R1.OID
             FROM PRM.MOVABLE_CALCULATION_PLAN R1
            WHERE (R1.CALCULATION_PLAN_PARENT_OID IS NULL OR R1.CALCULATION_PLAN_PARENT_OID = 0) AND R1.RELATED_YEAR=:relatedYear) CONNECT_BY_PRIOR  R.OID = R.CALCULATION_PLAN_PARENT_OID;

我不想要这样的输出: 我想要这样:

150       İLK MADDE VE MALZEMELER
150.1     İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU
150.1.1   İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU > ROL    <-----


150       İLK MADDE VE MALZEMELER
150.1     İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU
150.1.1   İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU > YAZI ARAÇLARI  
150.1.1.1 İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU > YAZI ARAÇLARI > ROLLER KALEM    <-----

如何实现?

提前致谢

一个解决方案将需要多次解决您的 table,因为您想要的输出可能有重复:部分路径(例如“150.1”)可能导致两个不同的兴趣叶,因此它将出现两次(或更多)。

请注意,您不需要在 start with 子句中重复 where 条件。无论如何都会应用它们,也适用于起始记录。

这里是查询:

SELECT NODE.CODE_PATH, NODE.NAME_PATH FROM
      (
      SELECT     OID,
                 SYS_CONNECT_BY_PATH(R.OID, ',') OID_PATH
      FROM       MOVABLE_CALCULATION_PLAN R
      WHERE      REGEXP_LIKE (R.CALCULATION_PLAN_NAME,'ROL')
                 AND CONNECT_BY_ISLEAF = 1
                 AND R.RELATED_YEAR = :relatedYear
      START WITH NVL(CALCULATION_PLAN_PARENT_OID, 0) = 0
      CONNECT BY PRIOR  R.OID = R.CALCULATION_PLAN_PARENT_OID
      ) LEAF
INNER JOIN
      (
      SELECT     SUBSTR(SYS_CONNECT_BY_PATH(R.CALCULATION_PLAN_CODE, '.'),2) CODE_PATH,
                 SUBSTR(SYS_CONNECT_BY_PATH(R.CALCULATION_PLAN_NAME, ' > '),4) NAME_PATH,
                 OID,
                 SYS_CONNECT_BY_PATH(R.OID, ',') OID_PATH
      FROM       MOVABLE_CALCULATION_PLAN R
      START WITH NVL(CALCULATION_PLAN_PARENT_OID, 0) = 0
      CONNECT BY PRIOR  R.OID = R.CALCULATION_PLAN_PARENT_OID
      ) NODE
ON NODE.OID = LEAF.OID
OR LEAF.OID_PATH LIKE '%,' || NODE.OID || ',%'

结果:

CODE_PATH   NAME_PATH
----------  ------------------------------------------------------------
150         İLK MADDE VE MALZEMELER
150.1       İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU
150.1.1     İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU > ROL
150         İLK MADDE VE MALZEMELER
150.1       İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU
150.1.1     İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU > YAZI ARAÇLARI
150.1.1.1   İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU > YAZI ARAÇLARI > ROL

还有一个fiddle.

想法是,在第一个子 select 中,您 select 叶子,具有您提供的 where 条件。然后你做另一个 sub-select that selects all nodes with their paths,没有任何过滤。最后,您将这些节点匹配为第一个过滤叶节点的下降线。

你想要的东西比较复杂,但它是可以解决的。不过,您需要构建多棵树:对于第一个查询,您通过 反向连接 ,从叶单元开始,构建直到根节点的分支,并跟踪leaf 使用 connect_by_root 函数构建分支。然后,在第二个查询中,您 connect by 基于第一个查询的结果,这次以正确的顺序进行,但另外匹配您之前跟踪的叶 ID。

with Q as
(
SELECT CONNECT_BY_ROOT(R.OID) leafid, R.*
FROM MOVABLE_CALCULATION_PLAN R
CONNECT BY R.OID = PRIOR R.CALCULATION_PLAN_PARENT_OID
START WITH R.RELATED_YEAR = 2015
  AND REGEXP_LIKE (R.CALCULATION_PLAN_NAME,'ROL')
  AND R.CALCULATION_PLAN_PARENT_OID != 0
  /*Following condition is replacement for CONNECT_BY_ISLEAF = 1,
    Since you're connecting in reverse you can't use it*/
  AND not exists 
    (select 'x' from MOVABLE_CALCULATION_PLAN R2
     where R2.CALCULATION_PLAN_PARENT_OID = R.OID)
)

select SUBSTR(SYS_CONNECT_BY_PATH(Q.CALCULATION_PLAN_CODE, '.'),2) CODE_PATH,
       SUBSTR(SYS_CONNECT_BY_PATH(Q.CALCULATION_PLAN_NAME, ' > '),4) NAME_PATH
  from Q
  CONNECT BY PRIOR  Q.OID = Q.CALCULATION_PLAN_PARENT_OID
  and prior Q.leafid = leafid
  START WITH NVL(CALCULATION_PLAN_PARENT_OID, 0) = 0

与按查询连接一样,性能可能是个问题,但从我在类似 table 结构上看到的情况来看,它仍然相当快。另见 http://sqlfiddle.com/#!4/dd5b68/6

P.S。以后一定要给我们提供样本数据和体面的描述你的情况,不要让我们破译你的问题,自己想出样本。