2

我有这个或多或少常见的查询来获取带有子路径的爆炸BOM:

select distinct
       LEVEL "level"
       ,sys_connect_by_path(msib.segment1, '|') as "PATH"
       ,msib2.segment1 as "CHILD ITEM"
       ,msib2.description
       ,bic.component_quantity
       ,TO_DATE(bic.IMPLEMENTATION_DATE) IMPLEMENTATION
       ,TO_DATE(bic.DISABLE_DATE)DISABLED
       ,(SELECT NAME FROM HR_ALL_ORGANIZATION_UNITS WHERE ORGANIZATION_ID = BIC.PK2_VALUE) ORGANIZATION
       ,bom.organization_id 
       ,BIC.ITEM_NUM SECUENCE
       ,bic.component_item_id CHILD_INVENTORY_ID
       , msib2.primary_uom_code UOM
from   bom.bom_components_b bic
       ,bom.bom_structures_b bom
       ,inv.mtl_system_items_b msib
       ,inv.mtl_system_items_b msib2
where  1=1
       and bic.bill_sequence_id = bom.bill_sequence_id
       and bom.assembly_item_id = msib.inventory_item_id
       and bom.organization_id = msib.organization_id
       and bic.component_item_id = msib2.inventory_item_id
       and bom.organization_id = msib2.organization_id
       and bom.organization_id IN (1269)
       and bom.alternate_bom_designator is NULL
       AND bic.DISABLE_DATE IS NULL <---------------- !!!LOOK HERE!!!
       connect by nocycle prior bic.codmponent_item_id = msib.inventory_item_id

D = 项目已禁用日期

--- 示例 0
父亲
   孩子0
   孩子1
   孩子2
应该返回:
 父亲|孩子0
 父亲|孩子1
 父亲|孩子2

--- 示例 1 父亲 孩子0 儿童 1 (D) 孩子2 应该返回: 父亲|孩子0 父亲|孩子2

--- 示例 2 父亲 儿童0 (D) 儿童 1 (D) 儿童 2 (D) 应该返回: 父亲(不管总成是空的,这将在 BOM 中更正)

--- 示例 3 父亲 (D) 孩子0 孩子1 孩子2 应该返回: 无效的

使用当前代码,如果程序集至少有一个项目处于活动状态,即使父亲不是,它也会被加载到查询中:

--- 示例 4
父亲 (D)
   儿童0 (D)
   儿童 1 (D)
   孩子2
回报:
 父亲|孩子0
 父亲|孩子1
 父亲|孩子2
应该返回:
 无效的

--- 示例 5
父亲 (D)
   孩子0
   孩子1
   孩子2
回报:
 父亲|孩子0
 父亲|孩子1
 父亲|孩子2
应该返回:
 无效的

我怎样才能防止这种情况?也就是说,只有当他们自己或父亲没有禁用日期时,我才需要检索项目。我的 BOM 最多有 9 个级别。谢谢!

编辑:对@mathguy 进行了修改:

    select distinct
           LEVEL "level"
           ,sys_connect_by_path(msib.segment1, '|') as "PATH"
           ,msib2.segment1 as "CHILD ITEM"
           <SNIP>
    from   bom.bom_components_b bic
           ,bom.bom_structures_b bom
           ,inv.mtl_system_items_b msib
           ,inv.mtl_system_items_b msib2
    where  1=1
           and bic.bill_sequence_id = bom.bill_sequence_id
           and bom.assembly_item_id = msib.inventory_item_id
           and bom.organization_id = msib.organization_id
           and bic.component_item_id = msib2.inventory_item_id
           and bom.organization_id = msib2.organization_id
           and bom.organization_id IN (1269)
           and bom.alternate_bom_designator is NULL
    START WITH msib.segment1 = 'GRANDPA' AND bic.DISABLE_DATE IS NULL 
    CONNECT BY nocycle prior bic.component_item_id = msib.inventory_item_id AND bic.DISABLE_DATE IS NULL 
           ORDER BY LEVEL,PATH ASC

并且查询返回的行数要少得多(好!)但是这个测试用例仍然失败:

--- 示例 4
爷爷
  父亲 (D)
    孩子0
    孩子1
    孩子2
应该返回:
  爷爷
回报:
  爷爷|父亲|孩子0
  爷爷|父亲|孩子1
  爷爷|父亲|孩子2

也许这与层次结构的深度有关?

4

1 回答 1

0

这个条件:

bic.DISABLE_DATE IS NULL

不应该在WHERE从句中,而应该在CONNECT BY从句中。更重要的是,由于CONNECT BY条件只适用于2级及以上,而不适用于初始行,您需要一个START WITH子句,并在那里添加相同的条件。

编辑- 并解释为什么会这样:您的分层查询以连接为起点。当对连接使用旧的 Oracle 风格的逗号语法时,WHERE子句中的某些条件被解析器视为连接条件(并且在分层步骤之前对其进行评估),而WHERE子句中的所有其他条件仅被评估分层步骤之后。

相反,如果层次结构基于单个表(或基于子查询/内联视图),则仅层次结构步骤之后才会评估所有子句条件。此外,如果您使用了 ANSI(SQL 标准)连接语法,则所有子句条件将仅在分层步骤之后进行评估;当然,连接的 ON 子句中的条件将在分层步骤之前进行评估。WHEREWHERE

于 2019-08-20T21:07:23.677 回答