Oracle EBS 后端查询中的数据丢失或不正确 (SQL)

Missing or incorrect data in Oracle EBS backend query (SQL)

我正在学习 Oracle 电子商务套件。使用 SQL 查询,我想获取所有已启用 BOM 并且其工作创建日期在过去 3 年内的项目 (ASSEMBLY_ITEM)。我编写的查询给了我想要的结果,但不知何故,组件项目列表 (COMPONENT_ITEM) 的数据不完整或某些项目的 (Null)。例如,我知道一些项目有 5 个组件,但在 SQL 查询输出中,同一个项目显示为只有一个组件。我正在验证来自 Oracle Apps 前端部分的数据。 到目前为止,这是我的查询:

SELECT DISTINCT BOM.BILL_SEQUENCE_ID,
  MSI.ORGANIZATION_ID,
  MSI.SEGMENT1 ASSEMBLY_ITEM,
  (SELECT SEGMENT1
  FROM MTL_SYSTEM_ITEMS_B
  WHERE INVENTORY_ITEM_ID=BIC.COMPONENT_ITEM_ID
  AND rownum             =1
  ) "COMPONENT_ITEM"
FROM BOM_OPERATIONAL_ROUTINGS BOR,
  BOM_BILL_OF_MATERIALS BOM,
  BOM_INVENTORY_COMPONENTS BIC,
  MTL_SYSTEM_ITEMS_B MSI
WHERE BOR.ASSEMBLY_ITEM_ID      = BOM.ASSEMBLY_ITEM_ID
AND BOR.ORGANIZATION_ID         = BOM.ORGANIZATION_ID
AND BOM.BILL_SEQUENCE_ID        = BIC.BILL_SEQUENCE_ID(+)
AND BOM.ASSEMBLY_ITEM_ID        = MSI.INVENTORY_ITEM_ID(+)
AND BOM.ORGANIZATION_ID         = MSI.ORGANIZATION_ID
AND MSI.ORGANIZATION_ID        IN (203, 204, 328)
AND MSI.BOM_ENABLED_FLAG        = 'Y'
AND NVL (MSI.ENABLED_FLAG, 'X') = 'Y'
AND BOR.ASSEMBLY_ITEM_ID       IN
  (SELECT DISTINCT PRIMARY_ITEM_ID
  FROM WIP_DISCRETE_JOBS WDJ
  WHERE BOR.ASSEMBLY_ITEM_ID = WDJ.PRIMARY_ITEM_ID
  AND WDJ.CREATION_DATE     >= ADD_MONTHS(SYSDATE, -12*3)
  ) 

我的查询应该 return 独特的组装项目,每个项目可能有一个或多个组件。

理想情况下,我应该得到所有独特的组装项目及其组件项目。我通过删除 BOM.BILL_SEQUENCE_ID = BIC.BILL_SEQUENCE_ID (+) 上的连接并删除查询末尾的半连接(“AND BOR.ASSEMBLY_ITEM_ID IN”部分来实现此目的,该部分基本上过滤了过去 3 年以来的结果。

连接部分不是真正的问题。除了这种方法之外,有没有什么方法可以根据过去 3 年创建的项目过滤结果? 我在这里错过了什么?

这里有几件事你可以做得更好。

首先,使用ANSI JOINS。我至少看到您的一些问题是由于 LEFT OUTER 加入时的不正确尝试造成的。使用 ANSI 语法将帮助您避免此类问题。

其次,不要使用 DISTINCT,除非您了解为什么有必要这样做。应该没有必要写你说你想要的查询。

第三,您不需要加入 BOM_OPERATIONAL_ROUTINGS -- 您不会将其用于任何用途(除非您尝试将其用作过滤器 -- 限制为 BOM有路由吗?)

第四,用EXISTS代替IN。 Oracle 的优化器大多足够智能,可以保护您免受 IN 过去可能给您带来的性能损失。尽管如此,EXISTS 更好地代表了您的意图 (imo),并且减少了对智能优化器的依赖。

最后,ROWNUM=1 获取组件项不是必需的。您也只需要限制 ORGANIZATION_ID

综上所述,以下查询应该非常接近您要查找的内容:

SELECT bom.bill_sequence_id,
       bom.organization_id,
       msi.segment1 assembly_item_id,
       bic.operation_seq_num,
       msic.segment1 component_item
FROM   bom_bill_of_materials bom
       LEFT JOIN mtl_system_items msi
         ON msi.organization_id = bom.organization_id
         AND msi.inventory_item_id = bom.assembly_item_id
         AND msi.enabled_flag = 'Y'
         AND msi.bom_enabled_flag = 'Y'
       LEFT JOIN bom_inventory_components bic ON bic.bill_sequence_id = bom.common_bill_sequence_id
       LEFT JOIN mtl_system_items msic
         ON msic.organization_id = bom.organization_id
         AND msic.inventory_item_id = bic.component_item_id
WHERE  bom.organization_id IN (203, 204, 328)
AND    EXISTS
         (SELECT 'job for item in last 3 years'
          FROM   wip_discrete_jobs wdj
          WHERE  wdj.primary_item_id = bom.assembly_item_id
          AND    wdj.creation_date >= ADD_MONTHS (SYSDATE, -36))
-- Unless you are loading a table with this, you may want to ORDER BY...
;