LEFT OUTER JOIN查询日期过滤异常问题求助
SQL查询条件优化方案
问题背景
采用LEFT OUTER JOIN关联PO_ATTRIBUTE_VALUES(因部分PO_ATTRIBUTE_VALUES行无对应PO_LINES_ARCHIVE_ALL记录),需求为返回以下两类数据:
PO_LINES_ARCHIVE_ALL(别名LN)中LAST_UPDATE_DATE在最近两天内的行PO_ATTRIBUTE_VALUES中LAST_UPDATE_DATE在最近两天内的行
当前遇到的问题:
- 不加
OR条件时,过滤掉了PO_ATTRIBUTE_VALUES中符合更新时间要求的行 - 直接加
OR ATTR.LAST_UPDATE_DATE > SYSDATE -2时,会返回PO_ATTRIBUTE_VALUES中未与LN关联的多余行
解决方案一:覆盖全场景(含无LN匹配的ATTR行)
用UNION ALL拆分两个逻辑分支,避免OR导致的左连接失效:
SELECT 'LINE_UPDATE' UPDATE_TYPE, LN.PO_HEADER_ID , LN.PO_LINE_ID, LN.LAST_UPDATE_DATE, LN.UNIT_PRICE, LN.VENDOR_PRODUCT_NUM, LN.UOM_CODE, ATTR.MANUFACTURER_PART_NUM, TLP.MANUFACTURER, LN_OLD.LAST_UPDATE_DATE LN_OLD_LAST_UPDATE_DT, ETP.TP_ITEM_NUMBER OLD_MFG_PART, LN_OLD.MANUFACTURER OLD_MFG, LN_OLD.VENDOR_PRODUCT_NUM OLD_VENDOR_ITEM, LN_OLD.UNIT_PRICE OLD_UNIT_PRICE, LN_OLD.UOM_CODE OLD_UOM_CODE, LN.ITEM_ID, ATTR.CREATION_DATE MFG_CREATION_DATE, ATTR.LAST_UPDATE_DATE MFG_LAST_UPDATE_DATE FROM PO_LINES_ARCHIVE_ALL LN LEFT OUTER JOIN EGP_SYSTEM_ITEMS ITM ON ITM.INVENTORY_ITEM_ID = LN.ITEM_ID AND ITM.ORGANIZATION_ID = 300000010136542 --Master Org. LEFT OUTER JOIN EGP_ITEM_RELATIONSHIPS_B EIR ON EIR.INVENTORY_ITEM_ID = LN.ITEM_ID AND EIR.ITEM_RELATIONSHIP_TYPE = 'MFG_PART_NUM' LEFT OUTER JOIN EGP_TRADING_PARTNER_ITEMS ETP ON ETP.TP_ITEM_ID = EIR.TP_ITEM_ID AND ETP.TP_TYPE = 'MANUFACTURER' LEFT OUTER JOIN PO_ATTRIBUTE_VALUES ATTR ON ATTR.PO_HEADER_ID = LN.PO_HEADER_ID AND ATTR.PO_LINE_ID = LN.PO_LINE_ID AND ATTR.LAST_UPDATE_DATE > SYSDATE - 22 AND ATTR.MANUFACTURER_PART_NUM <> ETP.TP_ITEM_NUMBER LEFT OUTER JOIN PO_ATTRIBUTE_VALUES_TLP TLP ON TLP.PO_HEADER_ID = LN.PO_HEADER_ID AND TLP.PO_LINE_ID = LN.PO_LINE_ID AND TLP.LAST_UPDATE_DATE > SYSDATE - 22 LEFT OUTER JOIN PO_LINES_ARCHIVE_ALL LN_OLD ON LN_OLD.PO_HEADER_ID = LN.PO_HEADER_ID AND LN_OLD.PO_LINE_ID = LN.PO_LINE_ID WHERE LN.LAST_UPDATE_DATE > SYSDATE - 2 UNION ALL SELECT 'LINE_UPDATE' UPDATE_TYPE, LN.PO_HEADER_ID , LN.PO_LINE_ID, LN.LAST_UPDATE_DATE, LN.UNIT_PRICE, LN.VENDOR_PRODUCT_NUM, LN.UOM_CODE, ATTR.MANUFACTURER_PART_NUM, TLP.MANUFACTURER, LN_OLD.LAST_UPDATE_DATE LN_OLD_LAST_UPDATE_DT, ETP.TP_ITEM_NUMBER OLD_MFG_PART, LN_OLD.MANUFACTURER OLD_MFG, LN_OLD.VENDOR_PRODUCT_NUM OLD_VENDOR_ITEM, LN_OLD.UNIT_PRICE OLD_UNIT_PRICE, LN_OLD.UOM_CODE OLD_UOM_CODE, LN.ITEM_ID, ATTR.CREATION_DATE MFG_CREATION_DATE, ATTR.LAST_UPDATE_DATE MFG_LAST_UPDATE_DATE FROM PO_ATTRIBUTE_VALUES ATTR LEFT OUTER JOIN PO_LINES_ARCHIVE_ALL LN ON ATTR.PO_HEADER_ID = LN.PO_HEADER_ID AND ATTR.PO_LINE_ID = LN.PO_LINE_ID LEFT OUTER JOIN EGP_SYSTEM_ITEMS ITM ON ITM.INVENTORY_ITEM_ID = LN.ITEM_ID AND ITM.ORGANIZATION_ID = 300000010136542 --Master Org. LEFT OUTER JOIN EGP_ITEM_RELATIONSHIPS_B EIR ON EIR.INVENTORY_ITEM_ID = LN.ITEM_ID AND EIR.ITEM_RELATIONSHIP_TYPE = 'MFG_PART_NUM' LEFT OUTER JOIN EGP_TRADING_PARTNER_ITEMS ETP ON ETP.TP_ITEM_ID = EIR.TP_ITEM_ID AND ETP.TP_TYPE = 'MANUFACTURER' LEFT OUTER JOIN PO_ATTRIBUTE_VALUES_TLP TLP ON TLP.PO_HEADER_ID = LN.PO_HEADER_ID AND TLP.PO_LINE_ID = LN.PO_LINE_ID AND TLP.LAST_UPDATE_DATE > SYSDATE - 22 LEFT OUTER JOIN PO_LINES_ARCHIVE_ALL LN_OLD ON LN_OLD.PO_HEADER_ID = LN.PO_HEADER_ID AND LN_OLD.PO_LINE_ID = LN.PO_LINE_ID WHERE ATTR.LAST_UPDATE_DATE > SYSDATE - 2 AND (LN.PO_LINE_ID IS NULL OR LN.LAST_UPDATE_DATE <= SYSDATE - 2);
方案说明
- 第一个查询:仅返回
LN表最近两天更新的行,保留原左连接逻辑,确保关联表数据正常匹配 - 第二个查询:从
ATTR表出发,返回其最近两天更新的行,同时过滤掉已在第一个查询中返回的记录(即LN也在最近两天更新的行),避免重复 - 若需去重,将
UNION ALL替换为UNION(性能略降)
解决方案二:仅保留有LN匹配的ATTR行
若不需要保留无对应LN的ATTR行,可简化WHERE条件,处理左连接后的NULL值:
SELECT 'LINE_UPDATE' UPDATE_TYPE, LN.PO_HEADER_ID , LN.PO_LINE_ID, LN.LAST_UPDATE_DATE, LN.UNIT_PRICE, LN.VENDOR_PRODUCT_NUM, LN.UOM_CODE, ATTR.MANUFACTURER_PART_NUM, TLP.MANUFACTURER, LN_OLD.LAST_UPDATE_DATE LN_OLD_LAST_UPDATE_DT, ETP.TP_ITEM_NUMBER OLD_MFG_PART, LN_OLD.MANUFACTURER OLD_MFG, LN_OLD.VENDOR_PRODUCT_NUM OLD_VENDOR_ITEM, LN_OLD.UNIT_PRICE OLD_UNIT_PRICE, LN_OLD.UOM_CODE OLD_UOM_CODE, LN.ITEM_ID, ATTR.CREATION_DATE MFG_CREATION_DATE, ATTR.LAST_UPDATE_DATE MFG_LAST_UPDATE_DATE FROM PO_LINES_ARCHIVE_ALL LN LEFT OUTER JOIN EGP_SYSTEM_ITEMS ITM ON ITM.INVENTORY_ITEM_ID = LN.ITEM_ID AND ITM.ORGANIZATION_ID = 300000010136542 --Master Org. LEFT OUTER JOIN EGP_ITEM_RELATIONSHIPS_B EIR ON EIR.INVENTORY_ITEM_ID = LN.ITEM_ID AND EIR.ITEM_RELATIONSHIP_TYPE = 'MFG_PART_NUM' LEFT OUTER JOIN EGP_TRADING_PARTNER_ITEMS ETP ON ETP.TP_ITEM_ID = EIR.TP_ITEM_ID AND ETP.TP_TYPE = 'MANUFACTURER' LEFT OUTER JOIN PO_ATTRIBUTE_VALUES ATTR ON ATTR.PO_HEADER_ID = LN.PO_HEADER_ID AND ATTR.PO_LINE_ID = LN.PO_LINE_ID AND ATTR.LAST_UPDATE_DATE > SYSDATE - 22 AND ATTR.MANUFACTURER_PART_NUM <> ETP.TP_ITEM_NUMBER LEFT OUTER JOIN PO_ATTRIBUTE_VALUES_TLP TLP ON TLP.PO_HEADER_ID = LN.PO_HEADER_ID AND TLP.PO_LINE_ID = LN.PO_LINE_ID AND TLP.LAST_UPDATE_DATE > SYSDATE - 22 LEFT OUTER JOIN PO_LINES_ARCHIVE_ALL LN_OLD ON LN_OLD.PO_HEADER_ID = LN.PO_HEADER_ID AND LN_OLD.PO_LINE_ID = LN.PO_LINE_ID WHERE LN.LAST_UPDATE_DATE > SYSDATE - 2 OR (ATTR.LAST_UPDATE_DATE > SYSDATE - 2 AND ATTR.PO_LINE_ID IS NOT NULL);
方案说明
- 通过
ATTR.PO_LINE_ID IS NOT NULL过滤左连接后ATTR为NULL的行,避免返回未与LN关联的多余数据 - 仅适用于不需要保留无对应
LN的ATTR行的场景
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

