基于临时表的SQL优化

前一阵子优化了个SQL,原代码如下:

 前一阵子,优化了一个SQL,原代码如下:
create or replace package body CUX_INV_DEAD_STOCK_DETAIL_PKG is
/* ================================================================================
  *   PROGRAM NAME:
  *                CUX_INV_DEAD_STOCK_DETAIL_PKG
  *
  *   PROGRAM STRUCTURE:
 
  *
  * ==============================================================================*/
  g_error varchar2(500);
  g_debug varchar2(500);
  procedure outlog(g_message in varchar2) is
  begin
    fnd_file.PUT_LINE(fnd_file.LOG,g_message);
  end outlog; --输出日志

  procedure output(g_message in varchar2) is
  begin
    fnd_file.PUT_LINE(fnd_file.OUTPUT,g_message);
    dbms_output.put_line(g_message);
  end output; --输出
  /* =================================================================================
  *   FUNCTION / PROCEDURE
  *   NAME : INV_DEAD_STOCK_DETAIL_MAIN
  *   DESCRIPTION: CUX:呆滞物料统计表
  
  *
  * ==================================================================================*/
  procedure inv_dead_stock_detail_main(o_errcode             out varchar2,
                                       o_errmess             out varchar2,
                                       p_org_id              in number,    --业务实体
                                       p_item_category       in varchar2,  --物料类型
                                       p_inventory_item_f    in varchar2,  --物料从
                                       p_inventory_item_t    in varchar2,  --物料至
                                       p_dead_days           in number     --呆滞天数
                                       ) is
  v_print_date         varchar2(30);  --打印日期
  v_ou                 varchar2(30);  --业务实体
  v_item_category      varchar2(100); --物料类型
  v_inventory_item_f   varchar2(100); --物料从
  v_inventory_item_t   varchar2(100); --物料至
  v_dead_days          varchar2(10);  --呆滞天数
  cursor c1 is
     select b.organization_id,
            b.item_category,
            b.item_sub_category,
            b.segment1,
            b.description,
            b.primary_unit_of_measure,
            b.item_cost,
            b.onhand_quantity,
            b.onhand_amount,
            b.last_transaction_date,
            b.dead_stock_days
       from (select a.organization_id,
                    a.item_category,
                    a.item_sub_category,
                    a.segment1,
                    a.description,
                    a.primary_unit_of_measure,
                    a.item_cost,
                    a.onhand_quantity,
                    a.onhand_amount,
                    max(mmt.transaction_date) last_transaction_date,
                    trunc(sysdate - max(mmt.transaction_date)) dead_stock_days
               from mtl_material_transactions mmt,
                    (select msib.organization_id,
                            msib.inventory_item_id,
                            mcb.segment1  item_category,     --物料大类
                            mcb.segment2  item_sub_category,  --物料小类
                            msib.segment1,
                            msib.description,
                            --onhand.transaction_uom_code,
                            msib.primary_unit_of_measure,
                            cic.item_cost,
                            sum(onhand.transaction_quantity) onhand_quantity,
                            (cic.item_cost * sum(onhand.transaction_quantity)) onhand_amount
                       from mtl_system_items_b           msib,
                            cst_item_costs               cic,
                            mtl_categories_b             mcb,
                            mtl_item_categories          mic,
                            mtl_onhand_quantities_detail onhand
                      where 1 = 1
                        and msib.inventory_item_id = onhand.inventory_item_id
                        and msib.organization_id = onhand.organization_id
                        and onhand.inventory_item_id = cic.inventory_item_id
                        and onhand.organization_id = cic.organization_id
                        and mcb.category_id = mic.category_id
                        and mic.inventory_item_id=msib.inventory_item_id
                        and mic.organization_id=msib.organization_id
                        and mcb.structure_id = 101
                        and mic.category_set_id = 1
                        and cic.cost_type_id = 3
                        and onhand.organization_id = p_org_id
                        --and msib.inventory_item_id=3073
                        and mcb.segment2=nvl(p_item_category,mcb.segment2)
                        and substr(onhand.subinventory_code,1,1)not in ('E','B')
                        and msib.segment1 between nvl(p_inventory_item_f,msib.segment1) and nvl(p_inventory_item_t,msib.segment1)
                      group by msib.organization_id,
                               msib.inventory_item_id,
                               mcb.segment1,
                               mcb.segment2,
                               msib.segment1,
                               msib.description,
                               msib.primary_unit_of_measure,
                               cic.item_cost) a
              where 1 = 1
                and a.organization_id = mmt.organization_id
                and a.inventory_item_id = mmt.inventory_item_id
                and mmt.transaction_type_id <>24
              group by a.organization_id,
                       a.item_category,
                       a.item_sub_category,
                       a.segment1,
                       a.description,
                       a.primary_unit_of_measure,
                       a.item_cost,
                       a.onhand_quantity,
                       a.onhand_amount) b
      where b.dead_stock_days > nvl(p_dead_days,0);
  begin
    --处理报表头信息
     g_debug        := '初始化公司LOGO和输入条件';
     --获取打印日期
     select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS')
     into v_print_date
     from dual;
     --获取业务实体
     select trim(hou.name)
      into v_ou
      from hr_operating_units hou
     where hou.organization_id = p_org_id;
     --获取物料类型
     v_item_category:=trim(p_item_category);
     --获取物料从
     v_inventory_item_f:=trim(p_inventory_item_f);
     --获取物料至
     v_inventory_item_t:=trim(p_inventory_item_t);
     --获取物料呆滞天数
     v_dead_days:=to_char(p_dead_days);
     --开始输出报表头信息
     g_debug          :='输出打印日期和用户输入条件';
     output('<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated by Oracle Reports version 10.1.2.3.0 -->
<CUXINVDEADSTOCK>
 <LIST_G_REPORT>');
    output('<PRINT_DATE>' || v_print_date || '</PRINT_DATE>');
    output('<OU>' || v_ou || '</OU>');
    output('<ITEM_CATEGORY>' || v_item_category || '</ITEM_CATEGORY>');
    output('<INVENTORY_ITEM_F>' || v_inventory_item_f || '</INVENTORY_ITEM_F>');
    output('<INVENTORY_ITEM_T>' || v_inventory_item_t || '</INVENTORY_ITEM_T>');
    output('<DEAD_DAYS>' || v_dead_days || '</DEAD_DAYS>');
    --主体数据内循环开始
      g_debug         :='主体数据内循环开始';
      for c1r in c1 loop
        output('<G_REPORT>');
          output('<CATEGORY_CODE>' || c1r.item_category ||'.'|| c1r.item_sub_category || '</CATEGORY_CODE>');
          output('<ITEM_CODE>' || c1r.segment1 || '</ITEM_CODE>');
          output('<ITEM_DESCRIPTION>' || cux_common_pkg.Xml_Format(c1r.description) || '</ITEM_DESCRIPTION>');
          output('<ITEM_UOM>' || c1r.primary_unit_of_measure || '</ITEM_UOM>');
          output('<ITEM_ONHAND>' || c1r.Onhand_Quantity || '</ITEM_ONHAND>');
          output('<LAST_TRANSACTION>' || to_char(c1r.last_transaction_date,'YYYY-MM-DD HH24:MI:SS') || '</LAST_TRANSACTION>');
          output('<DEAD_STOCK_DAYS>' || c1r.Dead_Stock_Days || '</DEAD_STOCK_DAYS>');
          output('<ITEM_COST>' || c1r.Item_Cost || '</ITEM_COST>');
          output('<ONHAND_AMOUNT>' || c1r.onhand_amount || '</ONHAND_AMOUNT>');
        output('</G_REPORT>');
      end loop;
      output('</LIST_G_REPORT>');
      output('</CUXINVDEADSTOCK>');
  exception
    when others then
       g_error := SQLERRM;
        INSERT INTO session_log --记录异常信息到异常表
        VALUES
          (SYSDATE, 'INVENTORY', 'CUX_INV_DEAD_STOCK_DETAIL_PKG', g_debug, g_error);
         COMMIT;
        outlog('出现错误');
  end inv_dead_stock_detail_main;
end CUX_INV_DEAD_STOCK_DETAIL_PKG;

这段代码运行的环境是oracle EBS R12中的一个查询呆滞物料的报表,运行的环境为IBM小机P系列(印象中应该P750)+v7000存储,这个报表跑出来的时间是最长达35分钟,在另一个低点的测试环境中用了将近七小时(具体配置就不提了),用10046 trace 出来的结果为(只取其中的主要的一段):

SELECT B.ORGANIZATION_ID, B.ITEM_CATEGORY, B.ITEM_SUB_CATEGORY, B.SEGMENT1, 
  B.DESCRIPTION, B.PRIMARY_UNIT_OF_MEASURE, B.ITEM_COST, B.ONHAND_QUANTITY, 
  B.ONHAND_AMOUNT, B.LAST_TRANSACTION_DATE, B.DEAD_STOCK_DAYS 
FROM
 (SELECT A.ORGANIZATION_ID, A.ITEM_CATEGORY, A.ITEM_SUB_CATEGORY, A.SEGMENT1, 
  A.DESCRIPTION, A.PRIMARY_UNIT_OF_MEASURE, A.ITEM_COST, A.ONHAND_QUANTITY, 
  A.ONHAND_AMOUNT, MAX(MMT.TRANSACTION_DATE) LAST_TRANSACTION_DATE, 
  TRUNC(SYSDATE - MAX(MMT.TRANSACTION_DATE)) DEAD_STOCK_DAYS FROM 
  MTL_MATERIAL_TRANSACTIONS MMT, (SELECT MSIB.ORGANIZATION_ID, 
  MSIB.INVENTORY_ITEM_ID, MCB.SEGMENT1 ITEM_CATEGORY, MCB.SEGMENT2 
  ITEM_SUB_CATEGORY, MSIB.SEGMENT1, MSIB.DESCRIPTION, 
  MSIB.PRIMARY_UNIT_OF_MEASURE, CIC.ITEM_COST, 
  SUM(ONHAND.TRANSACTION_QUANTITY) ONHAND_QUANTITY, (CIC.ITEM_COST * 
  SUM(ONHAND.TRANSACTION_QUANTITY)) ONHAND_AMOUNT FROM MTL_SYSTEM_ITEMS_B 
  MSIB, CST_ITEM_COSTS CIC, MTL_CATEGORIES_B MCB, MTL_ITEM_CATEGORIES MIC, 
  MTL_ONHAND_QUANTITIES_DETAIL ONHAND WHERE 1 = 1 AND MSIB.INVENTORY_ITEM_ID =
   ONHAND.INVENTORY_ITEM_ID AND MSIB.ORGANIZATION_ID = ONHAND.ORGANIZATION_ID 
  AND ONHAND.INVENTORY_ITEM_ID = CIC.INVENTORY_ITEM_ID AND 
  ONHAND.ORGANIZATION_ID = CIC.ORGANIZATION_ID AND MCB.CATEGORY_ID = 
  MIC.CATEGORY_ID AND MIC.INVENTORY_ITEM_ID=MSIB.INVENTORY_ITEM_ID AND 
  MIC.ORGANIZATION_ID=MSIB.ORGANIZATION_ID AND MCB.STRUCTURE_ID = 101 AND 
  MIC.CATEGORY_SET_ID = 1 AND CIC.COST_TYPE_ID = 3 AND ONHAND.ORGANIZATION_ID 
  = :B4 AND MCB.SEGMENT2=NVL(:B3 ,MCB.SEGMENT2) AND 
  SUBSTR(ONHAND.SUBINVENTORY_CODE,1,1)NOT IN ('E','B') AND MSIB.SEGMENT1 
  BETWEEN NVL(:B2 ,MSIB.SEGMENT1) AND NVL(:B1 ,MSIB.SEGMENT1) GROUP BY 
  MSIB.ORGANIZATION_ID, MSIB.INVENTORY_ITEM_ID, MCB.SEGMENT1, MCB.SEGMENT2, 
  MSIB.SEGMENT1, MSIB.DESCRIPTION, MSIB.PRIMARY_UNIT_OF_MEASURE, 
  CIC.ITEM_COST) A WHERE 1 = 1 AND A.ORGANIZATION_ID = MMT.ORGANIZATION_ID 
  AND A.INVENTORY_ITEM_ID = MMT.INVENTORY_ITEM_ID AND MMT.TRANSACTION_TYPE_ID 
  <>24 GROUP BY A.ORGANIZATION_ID, A.ITEM_CATEGORY, A.ITEM_SUB_CATEGORY, 
  A.SEGMENT1, A.DESCRIPTION, A.PRIMARY_UNIT_OF_MEASURE, A.ITEM_COST, 
  A.ONHAND_QUANTITY, A.ONHAND_AMOUNT) B WHERE B.DEAD_STOCK_DAYS > NVL(:B5 ,0)


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1    259.38    7987.81    1336813   28643548          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3    259.38    7987.81    1336813   28643548          0           0

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user id: 44     (recursive depth: 1)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  FILTER  (cr=0 pr=0 pw=0 time=0 us)
      0   HASH GROUP BY (cr=0 pr=0 pw=0 time=0 us cost=408 size=138 card=1)
2382290    NESTED LOOPS  (cr=28643548 pr=1336813 pw=0 time=7771837034 us)
2384353     NESTED LOOPS  (cr=26956486 pr=38996 pw=0 time=133943370 us cost=407 size=4968 card=36)
   4323      VIEW  (cr=26927194 pr=19148 pw=0 time=51978 us cost=377 size=118 card=1)
   4323       HASH GROUP BY (cr=26927194 pr=19148 pw=0 time=32507 us)
  39226        CONCATENATION  (cr=26927194 pr=19148 pw=0 time=200800799 us)
  39226         FILTER  (cr=26927194 pr=19148 pw=0 time=200782622 us)
  39226          NESTED LOOPS  (cr=26927194 pr=19148 pw=0 time=200762465 us)
  39226           NESTED LOOPS  (cr=26874154 pr=13992 pw=0 time=169916397 us cost=261 size=152 card=1)
  39249            NESTED LOOPS  (cr=26795777 pr=9888 pw=0 time=150089655 us cost=259 size=134 card=1)
4592133             NESTED LOOPS  (cr=17625783 pr=6874 pw=0 time=110462727 us cost=247 size=1368 card=12)
4592133              MERGE JOIN CARTESIAN (cr=10739 pr=402 pw=0 time=6150125 us cost=223 size=612 card=12)
    117               TABLE ACCESS BY INDEX ROWID MTL_CATEGORIES_B (cr=11 pr=10 pw=0 time=17429 us cost=4 size=34 card=1)
    117                INDEX RANGE SCAN MTL__CATEGORIES_B_N2 (cr=1 pr=1 pw=0 time=560 us cost=1 size=0 card=29)(object id 118829)
4592133               BUFFER SORT (cr=10728 pr=392 pw=0 time=4082113 us cost=219 size=884 card=52)
  39249                TABLE ACCESS BY INDEX ROWID MTL_ONHAND_QUANTITIES_DETAIL (cr=10728 pr=392 pw=0 time=709319 us cost=219 size=884 card=52)
  39249                 INDEX RANGE SCAN MTL_ONHAND_QUANTITIES_N5 (cr=385 pr=385 pw=0 time=575783 us cost=204 size=0 card=52)(object id 120237)
4592133              TABLE ACCESS BY INDEX ROWID MTL_SYSTEM_ITEMS_B (cr=17615044 pr=6472 pw=0 time=0 us cost=2 size=63 card=1)
4592133               INDEX UNIQUE SCAN MTL_SYSTEM_ITEMS_B_U1 (cr=9171958 pr=1125 pw=0 time=0 us cost=1 size=0 card=1)(object id 120986)
  39249             INDEX UNIQUE SCAN MTL_ITEM_CATEGORIES_U1 (cr=9169994 pr=3014 pw=0 time=0 us cost=1 size=20 card=1)(object id 119585)
  39226            INDEX UNIQUE SCAN CST_ITEM_COSTS_U1 (cr=78377 pr=4104 pw=0 time=0 us cost=1 size=0 card=1)(object id 208817)
  39226           TABLE ACCESS BY INDEX ROWID CST_ITEM_COSTS (cr=53040 pr=5156 pw=0 time=0 us cost=2 size=18 card=1)
      0         FILTER  (cr=0 pr=0 pw=0 time=0 us)
      0          NESTED LOOPS  (cr=0 pr=0 pw=0 time=0 us)
      0           NESTED LOOPS  (cr=0 pr=0 pw=0 time=0 us cost=115 size=152 card=1)
      0            NESTED LOOPS  (cr=0 pr=0 pw=0 time=0 us cost=113 size=134 card=1)
      0             NESTED LOOPS  (cr=0 pr=0 pw=0 time=0 us cost=110 size=117 card=1)
      0              MERGE JOIN CARTESIAN (cr=0 pr=0 pw=0 time=0 us cost=46 size=6208 card=64)
      0               TABLE ACCESS BY INDEX ROWID MTL_CATEGORIES_B (cr=0 pr=0 pw=0 time=0 us cost=4 size=34 card=1)
      0                INDEX RANGE SCAN MTL__CATEGORIES_B_N2 (cr=0 pr=0 pw=0 time=0 us cost=1 size=0 card=29)(object id 118829)
      0               BUFFER SORT (cr=0 pr=0 pw=0 time=0 us cost=42 size=17262 card=274)
      0                TABLE ACCESS BY INDEX ROWID MTL_SYSTEM_ITEMS_B (cr=0 pr=0 pw=0 time=0 us cost=42 size=17262 card=274)
      0                 INDEX RANGE SCAN MTL_SYSTEM_ITEMS_B_U2 (cr=0 pr=0 pw=0 time=0 us cost=7 size=0 card=49)(object id 408422)
      0              INDEX UNIQUE SCAN MTL_ITEM_CATEGORIES_U1 (cr=0 pr=0 pw=0 time=0 us cost=1 size=20 card=1)(object id 119585)
      0             TABLE ACCESS BY INDEX ROWID MTL_ONHAND_QUANTITIES_DETAIL (cr=0 pr=0 pw=0 time=0 us cost=3 size=17 card=1)
      0              INDEX RANGE SCAN MTL_ONHAND_QUANTITIES_N4 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)(object id 120239)
      0            INDEX UNIQUE SCAN CST_ITEM_COSTS_U1 (cr=0 pr=0 pw=0 time=0 us cost=1 size=0 card=1)(object id 208817)
      0           TABLE ACCESS BY INDEX ROWID CST_ITEM_COSTS (cr=0 pr=0 pw=0 time=0 us cost=2 size=18 card=1)
2384353      INDEX RANGE SCAN MTL_MATERIAL_TRANSACTIONS_N1 (cr=29292 pr=19848 pw=0 time=97162036 us cost=3 size=0 card=41)(object id 119944)
2382290     TABLE ACCESS BY INDEX ROWID MTL_MATERIAL_TRANSACTIONS (cr=1687062 pr=1297817 pw=0 time=0 us cost=31 size=720 card=36)


Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  db file sequential read                   1336813        0.64       7789.24
  latch free                                      1        0.00          0.00


从上面的执行计划中可以看到,大量的nested loops中逻辑读与物理读很大,而在外层嵌套中表

MTL_MATERIAL_TRANSACTIONS的数据量大,消耗的时间7771,837034us 即将近七小时,改写方案如下:
1.先创建临时表,用来存放内层结果:
2.将传进来的参数作判断处理,
3.将最外层表与内层结果用hash 返回结果;

结果如下:
CREATE GLOBAL TEMPORARY TABLE CUX.DEAD_MT
(
  ORGANIZATION_ID               NUMBER,  --MSIB_ORGANIZATION_ID
  INVENTORY_ITEM_ID             NUMBER,  --MSIB_INVENTORY_ITEM_ID
  item_category                 VARCHAR2(40 BYTE),  -- MCB_SEGMENT1 item_category,     --物料大类
  item_sub_category             VARCHAR2(40 BYTE),  -- MCB_SEGMENT2 item_sub_category,  --物料小类
  SEGMENT1                      VARCHAR2(40 BYTE),  --MSIB_SEGMENT1
  DESCRIPTION                   VARCHAR2(240 BYTE), --MSIB_DESCRIPTION
  PRIMARY_UNIT_OF_MEASURE  VARCHAR2(25 BYTE),  --MSIB_PRIMARY_UNIT_OF_MEASURE
  ITEM_COST                     NUMBER,      --CIC_ITEM_COST
  ONHAND_QUANTITY               NUMBER,   --sum(onhand.transaction_quantity) onhand_quantity,
  ONHAND_AMOUNT                 NUMBER  --(cic.item_cost * sum(onhand.transaction_quantity))
)
ON COMMIT DELETE ROWS;

create or replace package body CUX_INV_DEAD_STOCK_DETAIL_PKG is
/* ================================================================================
  *   PROGRAM NAME:
  *                CUX_INV_DEAD_STOCK_DETAIL_PKG
  *
  * ==============================================================================*/
  g_error varchar2(500);
  g_debug varchar2(500);
  procedure outlog(g_message in varchar2) is
  begin
    fnd_file.PUT_LINE(fnd_file.LOG,g_message);
  end outlog; --输出日志

  procedure output(g_message in varchar2) is
  begin
    fnd_file.PUT_LINE(fnd_file.OUTPUT,g_message);
    dbms_output.put_line(g_message);
  end output; --输出
  /* =================================================================================
  *   FUNCTION / PROCEDURE
  *   NAME : INV_DEAD_STOCK_DETAIL_MAIN
  *
  * ==================================================================================*/
  procedure inv_dead_stock_detail_main(o_errcode             out varchar2,
                                       o_errmess             out varchar2,
                                       p_org_id              in number,    --业务实体
                                       p_item_category       in varchar2,  --物料类型
                                       p_inventory_item_f    in varchar2,  --物料从
                                       p_inventory_item_t    in varchar2,  --物料至
                                       p_dead_days           in number     --呆滞天数
                                       ) is
  v_print_date         varchar2(30);  --打印日期
  v_ou                 varchar2(30);  --业务实体
  v_item_category      varchar2(100); --物料类型
  v_inventory_item_f   varchar2(100); --物料从
  v_inventory_item_t   varchar2(100); --物料至
  v_dead_days          varchar2(10);  --呆滞天数
  
  
 
  cursor c1 is  
  select    b.organization_id,
            b.item_category,
            b.item_sub_category,
            b.segment1,
            b.description,
            b.primary_unit_of_measure,
            b.item_cost,
            b.onhand_quantity,
            b.onhand_amount,
            b.last_transaction_date,
            b.dead_stock_days
from(            
select              /*+use_hash(mmt ,a)*/
                    a.ORGANIZATION_ID,
                       a.item_category,
                              -- a.INVENTORY_ITEM_ID,
                    a.item_sub_category,
                    a.segment1,
                    a.description,
                    a.primary_unit_of_measure,
                    a.item_cost,
                    a.onhand_quantity,
                    a.onhand_amount,
                    max(mmt.transaction_date) last_transaction_date,
                    trunc(TO_DATE('2015-3-30 11:36:00','YYYY-MM-DD HH24:MI:SS') - max(mmt.transaction_date)) dead_stock_days
                    --trunc(sysdate - max(mmt.transaction_date)) dead_stock_days
      from mtl_material_transactions mmt, DEAD_MT a
       where 1 = 1
                and a.organization_id = mmt.organization_id
                and a.inventory_item_id = mmt.inventory_item_id
                and mmt.transaction_type_id <>24
                and a.item_sub_category=nvl(p_item_category,a.item_sub_category)
                --and a.segment1 between nvl(null,a.segment1) and nvl(null,a.segment1)
                group by a.organization_id,
                       a.item_category,
                       a.item_sub_category,
                       a.segment1,
                       a.description,
                       a.primary_unit_of_measure,
                       a.item_cost,
                       a.onhand_quantity,
                       a.onhand_amount) b    
where     b.dead_stock_days > nvl(p_dead_days,0);                            
                                                      

  begin
  if (p_inventory_item_f is null and p_inventory_item_t is null)
  then
  insert /* +append*/into  DEAD_MT
select msib.organization_id,
                            msib.inventory_item_id,
                            mcb.segment1  item_category,     --物料大类
                            mcb.segment2  item_sub_category,  --物料小类
                            msib.segment1,
                            msib.description,
                            --onhand.transaction_uom_code,
                            msib.primary_unit_of_measure,
                            cic.item_cost,
                            sum(onhand.transaction_quantity) onhand_quantity,
                            (cic.item_cost * sum(onhand.transaction_quantity)) onhand_amount
                       from mtl_system_items_b           msib,  
                            cst_item_costs               cic,  
                            mtl_categories_b             mcb,  
                            mtl_item_categories          mic,  
                            mtl_onhand_quantities_detail onhand   
                        where 1=1    
                        and msib.inventory_item_id = onhand.inventory_item_id
                        and msib.organization_id = onhand.organization_id
                        and onhand.inventory_item_id = cic.inventory_item_id
                        and onhand.organization_id = cic.organization_id
                        and mcb.category_id = mic.category_id
                        and mic.inventory_item_id=msib.inventory_item_id
                        and mic.organization_id=msib.organization_id
                        and mcb.structure_id = 101
                        and mic.category_set_id = 1
                        and cic.cost_type_id = 3
                        and onhand.organization_id = p_org_id
                        --and msib.inventory_item_id=3073
                     -- and mcb.segment2=nvl(null,mcb.segment2)  and mcb.segment2=nvl(p_item_category,mcb.segment2)
                        and substr(onhand.subinventory_code,1,1)not in ('E','B')
                   --  and msib.segment1 between nvl(null,msib.segment1) and nvl(null,msib.segment1)
                     --   and msib.segment1 between nvl(p_inventory_item_f,msib.segment1) and nvl(p_inventory_item_t,msib.segment1)
                      group by msib.organization_id,
                               msib.inventory_item_id,
                               mcb.segment1,
                               mcb.segment2,
                               msib.segment1,
                               msib.description,
                               msib.primary_unit_of_measure,
                               cic.item_cost;
end if;                               
 if   ( p_inventory_item_f is not null and p_inventory_item_t is not null)
 then
    insert into  DEAD_MT
select msib.organization_id,
                            msib.inventory_item_id,
                            mcb.segment1  item_category,     --物料大类
                            mcb.segment2  item_sub_category,  --物料小类
                            msib.segment1,
                            msib.description,
                            --onhand.transaction_uom_code,
                            msib.primary_unit_of_measure,
                            cic.item_cost,
                            sum(onhand.transaction_quantity) onhand_quantity,
                            (cic.item_cost * sum(onhand.transaction_quantity)) onhand_amount
                       from mtl_system_items_b           msib,  
                            cst_item_costs               cic,  
                            mtl_categories_b             mcb,  
                            mtl_item_categories          mic,  
                            mtl_onhand_quantities_detail onhand   
                        where 1=1    
                        and msib.inventory_item_id = onhand.inventory_item_id
                        and msib.organization_id = onhand.organization_id
                        and onhand.inventory_item_id = cic.inventory_item_id
                        and onhand.organization_id = cic.organization_id
                        and mcb.category_id = mic.category_id
                        and mic.inventory_item_id=msib.inventory_item_id
                        and mic.organization_id=msib.organization_id
                        and mcb.structure_id = 101
                        and mic.category_set_id = 1
                        and cic.cost_type_id = 3
                        and onhand.organization_id = p_org_id
                        --and msib.inventory_item_id=3073
                          --and mcb.segment2=nvl(null,mcb.segment2) 
                          --and mcb.segment2=p_item_category
                        and substr(onhand.subinventory_code,1,1)not in ('E','B')
                   --  and msib.segment1 between nvl(null,msib.segment1) and nvl(null,msib.segment1)
                        and msib.segment1 between p_inventory_item_f and p_inventory_item_t
                      group by msib.organization_id,
                               msib.inventory_item_id,
                               mcb.segment1,
                               mcb.segment2,
                               msib.segment1,
                               msib.description,
                               msib.primary_unit_of_measure,
                               cic.item_cost;
 
 end if;
 if ( p_inventory_item_f is not null and p_inventory_item_t is null) 
 then
   insert into  DEAD_MT
select msib.organization_id,
                            msib.inventory_item_id,
                            mcb.segment1  item_category,     --物料大类
                            mcb.segment2  item_sub_category,  --物料小类
                            msib.segment1,
                            msib.description,
                            --onhand.transaction_uom_code,
                            msib.primary_unit_of_measure,
                            cic.item_cost,
                            sum(onhand.transaction_quantity) onhand_quantity,
                            (cic.item_cost * sum(onhand.transaction_quantity)) onhand_amount
                       from mtl_system_items_b           msib,  
                            cst_item_costs               cic,  
                            mtl_categories_b             mcb,  
                            mtl_item_categories          mic,  
                            mtl_onhand_quantities_detail onhand   
                        where 1=1    
                        and msib.inventory_item_id = onhand.inventory_item_id
                        and msib.organization_id = onhand.organization_id
                        and onhand.inventory_item_id = cic.inventory_item_id
                        and onhand.organization_id = cic.organization_id
                        and mcb.category_id = mic.category_id
                        and mic.inventory_item_id=msib.inventory_item_id
                        and mic.organization_id=msib.organization_id
                        and mcb.structure_id = 101
                        and mic.category_set_id = 1
                        and cic.cost_type_id = 3
                        and onhand.organization_id = p_org_id
                        --and msib.inventory_item_id=3073
                          --and mcb.segment2=nvl(null,mcb.segment2) 
                        and mcb.segment2=p_item_category
                        and substr(onhand.subinventory_code,1,1)not in ('E','B')
                   --  and msib.segment1 between nvl(null,msib.segment1) and nvl(null,msib.segment1)
                        and msib.segment1 between p_inventory_item_f and msib.segment1
                      group by msib.organization_id,
                               msib.inventory_item_id,
                               mcb.segment1,
                               mcb.segment2,
                               msib.segment1,
                               msib.description,
                               msib.primary_unit_of_measure,
                               cic.item_cost;
end if;
    --处理报表头信息
     g_debug        := '初始化公司LOGO和输入条件';
     --获取打印日期
     select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS')
     into v_print_date
     from dual;
     --获取业务实体
     select trim(hou.name)
      into v_ou
      from hr_operating_units hou
     where hou.organization_id = p_org_id;
     --获取物料类型
     v_item_category:=trim(p_item_category);
     --获取物料从
     v_inventory_item_f:=trim(p_inventory_item_f);
     --获取物料至
     v_inventory_item_t:=trim(p_inventory_item_t);
     --获取物料呆滞天数
     v_dead_days:=to_char(p_dead_days);
     --开始输出报表头信息
     g_debug          :='输出打印日期和用户输入条件';
     output('<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated by Oracle Reports version 10.1.2.3.0 -->
<CUXINVDEADSTOCK>
 <LIST_G_REPORT>');
    output('<PRINT_DATE>' || v_print_date || '</PRINT_DATE>');
    output('<OU>' || v_ou || '</OU>');
    output('<ITEM_CATEGORY>' || v_item_category || '</ITEM_CATEGORY>');
    output('<INVENTORY_ITEM_F>' || v_inventory_item_f || '</INVENTORY_ITEM_F>');
    output('<INVENTORY_ITEM_T>' || v_inventory_item_t || '</INVENTORY_ITEM_T>');
    output('<DEAD_DAYS>' || v_dead_days || '</DEAD_DAYS>');
    --主体数据内循环开始
      g_debug         :='主体数据内循环开始';
      for c1r in c1 loop
        output('<G_REPORT>');
          output('<CATEGORY_CODE>' || c1r.item_category ||'.'|| c1r.item_sub_category || '</CATEGORY_CODE>');
          output('<ITEM_CODE>' || c1r.segment1 || '</ITEM_CODE>');
          output('<ITEM_DESCRIPTION>' || cux_common_pkg.Xml_Format(c1r.description) || '</ITEM_DESCRIPTION>');
          output('<ITEM_UOM>' || c1r.primary_unit_of_measure || '</ITEM_UOM>');
          output('<ITEM_ONHAND>' || c1r.Onhand_Quantity || '</ITEM_ONHAND>');
          output('<LAST_TRANSACTION>' || to_char(c1r.last_transaction_date,'YYYY-MM-DD HH24:MI:SS') || '</LAST_TRANSACTION>');
          output('<DEAD_STOCK_DAYS>' || c1r.Dead_Stock_Days || '</DEAD_STOCK_DAYS>');
          output('<ITEM_COST>' || c1r.Item_Cost || '</ITEM_COST>');
          output('<ONHAND_AMOUNT>' || c1r.onhand_amount || '</ONHAND_AMOUNT>');
        output('</G_REPORT>');
      end loop;
      output('</LIST_G_REPORT>');
      output('</CUXINVDEADSTOCK>');
  exception
    when others then
       g_error := SQLERRM;
        INSERT INTO session_log --记录异常信息到异常表
        VALUES
          (SYSDATE, 'INVENTORY', 'CUX_INV_DEAD_STOCK_DETAIL_PKG', g_debug, g_error);
         COMMIT;
        outlog('出现错误');
  end inv_dead_stock_detail_main;
end CUX_INV_DEAD_STOCK_DETAIL_PKG;

这样变更后,在正式环境中运行的时为3分钟46秒,测试环境,从7小时变是20分钟。

你可能感兴趣的:(SQL优化)