【问题标题】:Get path hierarhy using connect by prior vertical instead of horizontal in Oracle?在Oracle中使用先前垂直而不是水平连接来获取路径层次结构?
【发布时间】:2015-12-21 13:43:26
【问题描述】:

您好,我有一个使用 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    <-----

如何做到这一点?

提前致谢

【问题讨论】:

  • 删除AND REGEXP_LIKE (R.CALCULATION_PLAN_NAME,'ROL') 可能吗?
  • @Timekiller,如果我删除它,如何按名称搜索。我想使用 like 运算符按名称搜索,然后我正在等待看到一棵或多棵像上面显示的层次树。跨度>
  • 有人评论吗?

标签: sql oracle11g hierarchy connect-by


【解决方案1】:

解决方案需要多次处理您的表,因为您所需的输出可能有重复:部分路径(例如“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

这个想法是,在第一个子选择中,您选择叶子,并使用您提供的 where 条件。然后您执行另一个子选择,选择 all 节点及其路径,而不进行任何过滤。最后,您将这些节点匹配为第一个过滤叶节点的下降线。

【讨论】:

  • 这是一个很好的尝试,但我认为 OP 只想显示 leaf 包含 ROL 的树。即使在您的小提琴中,它也会显示 ID 为 5 的组,其中包含其他条目。此外,由于OR CONNECT_BY_ISLEAF = 0,您的查询将显示所有不包含ROL 的组 - 看看你自己,sqlfiddle.com/#!4/c4e4f/1
  • 感谢您指出这一点。我更新了查询来处理这个问题。
【解决方案2】:

你想要的是相当复杂的,但它是可以解决的。但是,您需要构建多棵树:在第一个查询中,您通过 反向连接,从叶子单元开始,构建分支到根节点,并跟踪您的叶子'使用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

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

附:以后,请务必向我们提供样本数据和对您的情况的体面描述,不要让我们破译您的查询并自己想出样本。

【讨论】:

    猜你喜欢
    • 2021-11-27
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-27
    • 1970-01-01
    相关资源
    最近更新 更多