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...
;
我正在学习 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...
;