You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于ITEM_ID关联两个独立SQL查询且避免结果相互干扰?

解决SQL查询中动态日期范围与年度平均值结果失真问题

我编写了SQL查询,用于根据动态日期范围(如2024-10-01至2024-10-28)计算平均值,对应列是SUM(ROUND(QTY_AVG.AVERAGE,2)) DATE_RANGE_AVERAGE。另外有个子查询QTY_AVG_YEAR计算硬编码日期范围的年度平均值,原本想通过QTY_AVG_YEAR.ITEM_ID = rsl.ITEM_ID关联主查询,把年度平均值列放在动态平均值列旁边,但这个关联导致DATE_RANGE_AVERAGE结果失真——因为年度查询引入了全年的更多行数据。需要实现两个独立查询,各自生成不受影响的结果,再基于ITEM_ID合并到同一行。

原SQL代码

select         
     esib.item_number inv_item_id, --:INV_ITEM_ID, 
       pla.item_description descr254_mixed

,SUM(ROUND(QTY_AVG.AVERAGE,2)) DATE_RANGE_AVERAGE
--,SUM(ROUND(QTY_AVG_YEAR.AVERAGE_YEAR,2)) YEAR_AVERAGE

  from po_headers_all pha,
       po_lines_all pla,
       po_line_locations_all plla,
       po_distributions_all pda,
       rcv_shipment_headers rsh,
       rcv_shipment_lines rsl,
       rcv_transactions rt,
      egp_system_items_b esib,
       inv_org_parameters iop,
       GL_CODE_COMBINATIONS GCC,
     HR_ALL_ORGANIZATION_UNITS_F_VL HR,
    INV_UOM_CONVERSIONS INTRACONV                   
       
     , (SELECT SUM(LN.QUANTITY_RECEIVED)/(:P_TO_DATE - :P_FROM_DATE) AVERAGE, SHIPMENT_HEADER_ID, shipment_line_id
       FROM rcv_shipment_lines LN
       WHERE LN.CREATION_DATE >= :P_FROM_DATE
         AND LN.CREATION_DATE <= :P_TO_DATE
       GROUP BY SHIPMENT_HEADER_ID, shipment_line_id ) QTY_AVG      
             
     , (SELECT SUM(LN.QUANTITY_RECEIVED)/365 AVERAGE_YEAR, SHIPMENT_HEADER_ID, shipment_line_id, ITEM_ID
       FROM rcv_shipment_lines LN
       WHERE TO_CHAR(LN.CREATION_DATE, 'yyyy-mm-dd') >= '2023-10-23'
         AND TO_CHAR(LN.CREATION_DATE, 'yyyy-mm-dd') <= '2024-09-30'
          --AND LN.ITEM_ID = :INV_ITEM_ID    --rsl.ITEM_ID
          --AND ITEM_ID =100000030622932
       GROUP BY SHIPMENT_HEADER_ID, shipment_line_id, ITEM_ID ) QTY_AVG_YEAR  

       
WHERE pha.po_header_id = pla.po_header_id
   and pla.po_line_id = plla.po_line_id
   and plla.line_location_id = pda.line_location_id
   and rt.po_header_id = pha.po_header_id
   AND transaction_type = 'RECEIVE'
   AND GCC.CODE_COMBINATION_ID = PDA.CODE_COMBINATION_ID    
AND pha.SEGMENT1 = NVL(:P_PO_ID, pha.SEGMENT1)   
AND HR.organization_id = rt.ORGANIZATION_ID                                                       
AND INTRACONV.UOM_CODE(+) = CASE WHEN esib.UNIT_OF_ISSUE IS NOT NULL THEN esib.UNIT_OF_ISSUE ELSE rsl.UOM_CODE END
AND INTRACONV.INVENTORY_ITEM_ID(+)  = esib.INVENTORY_ITEM_ID 

      AND QTY_AVG.SHIPMENT_HEADER_ID = rsl.SHIPMENT_HEADER_ID
      AND QTY_AVG.shipment_line_id = rsl.shipment_line_id      
      
  AND QTY_AVG_YEAR.ITEM_ID = rsl.ITEM_ID         
  
  AND YEAR_AVERAGE.ITEM_ID(+) = rsl.ITEM_ID

AND rt.transaction_date BETWEEN

to_date(nvl( to_char(:P_FROM_DATE,'yyyy-mm-dd') , to_char(sysdate - 30, 'YYYY-MM-DD')) ||' 00:00:00', 'YYYY-MM-DD HH24:Mi:SS')

 AND 

to_date(nvl( to_char(:P_TO_DATE,'yyyy-mm-dd') , to_char(sysdate - 1 , 'YYYY-MM-DD')) ||' 23:59:59', 'YYYY-MM-DD HH24:Mi:SS')
 
 AND esib.item_number IN ('111090',
               '112252',
               '14438',
               '20',
               '112399',
               '110844',
               '221',
               '85866',
               '112304',
               '219',
               '112078' )

GROUP BY 
        esib.item_number , 
        pla.item_description  

仅保留动态日期范围列的正确结果

INV_ITEM_ID  DESCR254_MIXED               DATE_RANGE_AVERAGE
------------------------------------------------------------
219          SALINE, 1000CC IRRIGATION    5.37
221          SALINE, 3000 CC IRRIGATION   5.36
14438        SOLN, SOD CHLOR .9% 250CC    1.64
112252       SOLUTION INTRAVENOUS SODIUM  2.41
112304       SOL IRRIG NACL 0.9% USP      3.56

同时保留两列的错误结果

INV_ITEM_ID    DESCR254_MIXED               DATE_RANGE_AVERAGE  YEAR_AVERAGE
-----------------------------------------------------------------------------
219            SALINE, 1000CC IRRIGATION    1154.55             72.39
221            SALINE, 3000 CC IRRIGATION   766.48              105.1
14438          SOLN, SOD CHLOR .9% 250CC    354.24              30.25
112252         SOLUTION INTRAVENOUS SODIUM  245.82              11.52
112304         SOL IRRIG NACL 0.9% USP      202.92              7.6

解决方案

核心思路是分别计算动态日期范围的平均值和年度平均值,得到两个独立的结果集,再通过ITEM_ID关联合并。

最终SQL代码

WITH date_range_avg AS (
    -- 计算动态日期范围的平均值
    SELECT 
        esib.item_number inv_item_id,
        pla.item_description descr254_mixed,
        SUM(ROUND(QTY_AVG.AVERAGE, 2)) DATE_RANGE_AVERAGE
    FROM po_headers_all pha
    JOIN po_lines_all pla ON pha.po_header_id = pla.po_header_id
    JOIN po_line_locations_all plla ON pla.po_line_id = plla.po_line_id
    JOIN po_distributions_all pda ON plla.line_location_id = pda.line_location_id
    JOIN rcv_transactions rt ON rt.po_header_id = pha.po_header_id
    JOIN rcv_shipment_lines rsl ON rt.shipment_header_id = rsl.shipment_header_id 
                               AND rt.shipment_line_id = rsl.shipment_line_id
    JOIN egp_system_items_b esib ON rsl.item_id = esib.inventory_item_id
    JOIN GL_CODE_COMBINATIONS GCC ON GCC.CODE_COMBINATION_ID = PDA.CODE_COMBINATION_ID
    JOIN HR_ALL_ORGANIZATION_UNITS_F_VL HR ON HR.organization_id = rt.ORGANIZATION_ID
    LEFT JOIN INV_UOM_CONVERSIONS INTRACONV 
        ON INTRACONV.UOM_CODE = CASE WHEN esib.UNIT_OF_ISSUE IS NOT NULL THEN esib.UNIT_OF_ISSUE ELSE rsl.UOM_CODE END
        AND INTRACONV.INVENTORY_ITEM_ID = esib.INVENTORY_ITEM_ID
    JOIN (
        SELECT 
            SUM(LN.QUANTITY_RECEIVED)/(:P_TO_DATE - :P_FROM_DATE) AVERAGE,
            SHIPMENT_HEADER_ID,
            shipment_line_id
        FROM rcv_shipment_lines LN
        WHERE LN.CREATION_DATE >= :P_FROM_DATE
          AND LN.CREATION_DATE <= :P_TO_DATE
        GROUP BY SHIPMENT_HEADER_ID, shipment_line_id
    ) QTY_AVG ON QTY_AVG.SHIPMENT_HEADER_ID = rsl.SHIPMENT_HEADER_ID 
              AND QTY_AVG.shipment_line_id = rsl.shipment_line_id
    WHERE rt.transaction_type = 'RECEIVE'
      AND pha.SEGMENT1 = NVL(:P_PO_ID, pha.SEGMENT1)
      AND rt.transaction_date BETWEEN 
            TO_DATE(NVL(TO_CHAR(:P_FROM_DATE,'yyyy-mm-dd'), TO_CHAR(SYSDATE - 30, 'YYYY-MM-DD')) ||' 00:00:00', 'YYYY-MM-DD HH24:Mi:SS')
            AND 
            TO_DATE(NVL(TO_CHAR(:P_TO_DATE,'yyyy-mm-dd'), TO_CHAR(SYSDATE - 1, 'YYYY-MM-DD')) ||' 23:59:59', 'YYYY-MM-DD HH24:Mi:SS')
      AND esib.item_number IN ('111090','112252','14438','20','112399','110844','221','85866','112304','219','112078')
    GROUP BY esib.item_number, pla.item_description
),
year_avg AS (
    -- 计算年度平均值
    SELECT 
        esib.item_number inv_item_id,
        SUM(ROUND(SUM(LN.QUANTITY_RECEIVED)/365, 2)) YEAR_AVERAGE
    FROM rcv_shipment_lines LN
    JOIN egp_system_items_b esib ON LN.item_id = esib.inventory_item_id
    WHERE LN.CREATION_DATE BETWEEN TO_DATE('2023-10-23', 'yyyy-mm-dd') 
                               AND TO_DATE('2024-09-30', 'yyyy-mm-dd')
      AND esib.item_number IN ('111090','112252','14438','20','112399','110844','221','85866','112304','219','112078')
    GROUP BY esib.item_number
)
-- 合并两个结果集
SELECT 
    dra.inv_item_id,
    dra.descr254_mixed,
    dra.DATE_RANGE_AVERAGE,
    ya.YEAR_AVERAGE
FROM date_range_avg dra
LEFT JOIN year_avg ya ON dra.inv_item_id = ya.inv_item_id;

关键说明

  1. 独立计算:两个CTE(date_range_avg和year_avg)分别计算各自的平均值,避免了原查询中关联年度数据导致的行膨胀,确保结果不受互相干扰。
  2. 显式JOIN:将原查询的逗号连接语法改为显式JOIN,逻辑更清晰,减少隐式笛卡尔积的风险。
  3. LEFT JOIN合并:使用LEFT JOIN确保即使某些物品没有年度数据,动态日期范围的结果依然能正常显示,不会被过滤掉。

内容的提问来源于stack exchange,提问作者Nick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 17:47:02