首页 > 代码库 > 10g full join 优化

10g full join 优化

今天一个女生咨询我报名学优化。聊着聊着就让我优化一个sql,贴给大家看一下

select (case
         when grouping(allwo.workshop_code) = 1 then
          ‘‘
         else
          nvl(max(allwo.workshop_code), ‘未维护车间‘)
       end) workshop_code,
       DECODE(TO_NUMBER(substr(Item_code,
                               4,
                               INSTR(Item_code, ‘M‘, 1, 2) - 4)) / 10,
              NULL,
              ‘合计‘,
              TO_NUMBER(substr(Item_code, 4, INSTR(Item_code, ‘M‘, 1, 2) - 4)) / 10 || ‘M‘) xiangsu,
       (case
         when grouping(item_code) = 1 then
          ‘‘
         else
          max(part_spec)
       end) part_spec,
       (case
         when grouping(item_code) = 1 then
          ‘‘
         else
          max(type)
       end) type,
       nvl(wo_code, ‘‘) wo_code,
       sum(qty) qty,
       sum(UsedQty) qx,
       sum(db) db,
       sum(wb) wb,
       sum(HM) HM,
       sum(成品站) 成品站,
       sum(烘烤) 烘烤,
       sum(十级产出) 十级产出,
       sum(分粒接收) 分粒接收,
       sum(分粒修边) 分粒修边,
       sum(焊接) 焊接,
       sum(喷码打标) 喷码打标,
       sum(撕膜) 撕膜,
       sum(调焦) 调焦,
       sum(点胶) 点胶,
       sum(点胶全检) 点胶全检,
       sum(功测一) 功测一,
       sum(功测接收修复) 功测接收修复,
       sum(功测二) 功测二,
       sum(QC功测) QC功测,
       sum(远焦烧录) 远焦烧录,
       sum(近焦烧录) 近焦烧录,
       sum(OTP烧录) OTP烧录,
       sum(OTP检测) OTP检测,
       sum(QCOTP烧录) QCOTP烧录,
       sum(背胶) 背胶,
       sum(外观) 外观,
       sum(OS测试) OS测试,
       sum(CCD检验) CCD检验,
       sum(贴膜) 贴膜,
       sum(包装) 包装,
       sum(包装入库) 包装入库,
       sum(修复接收) 修复接收,
       sum(修复维修) 修复维修,
       sum(脏点测试) 脏点测试,
       sum(修复焊接) 修复焊接,
       sum(修复修边) 修复修边,
       sum(修复调焦) 修复调焦,
       sum(修复功能测试) 修复功能测试,
       sum(修复转出) 修复转出
  from (select COALESCE(wocode,
                        gxcl.wo_code,
                        bz.wo_code,
                        xiufujieshou.wo_code) wocode,
               nvl(UsedQty, 0) UsedQty,
               nvl(db, 0) db,
               nvl(wb, 0) wb,
               nvl(成品站, 0) 成品站,
               nvl(HM, 0) HM,
               nvl(烘烤, 0) 烘烤,
               nvl(十级产出, 0) 十级产出,
               nvl(分粒接收, 0) 分粒接收,
               nvl(分粒修边, 0) 分粒修边,
               nvl(焊接, 0) 焊接,
               nvl(喷码打标, 0) 喷码打标,
               nvl(撕膜, 0) 撕膜,
               nvl(调焦, 0) 调焦,
               nvl(点胶, 0) 点胶,
               nvl(点胶全检, 0) 点胶全检,
               nvl(功测一, 0) 功测一,
               nvl(功测接收修复, 0) 功测接收修复,
               nvl(功测二, 0) 功测二,
               nvl(QC功测, 0) QC功测,
               nvl(远焦烧录, 0) 远焦烧录,
               nvl(近焦烧录, 0) 近焦烧录,
               nvl(OTP烧录, 0) OTP烧录,
               nvl(OTP检测, 0) OTP检测,
               nvl(QCOTP烧录, 0) QCOTP烧录,
               nvl(背胶, 0) 背胶,
               nvl(外观, 0) 外观,
               nvl(OS测试, 0) OS测试,
               nvl(CCD检验, 0) CCD检验,
               nvl(贴膜, 0) 贴膜,
               nvl(修复接收, 0) 修复接收,
               nvl(修复维修, 0) 修复维修,
               nvl(脏点测试, 0) 脏点测试,
               nvl(修复焊接, 0) 修复焊接,
               nvl(修复修边, 0) 修复修边,
               nvl(修复调焦, 0) 修复调焦,
               nvl(修复功能测试, 0) 修复功能测试,
               nvl(修复转出, 0) 修复转出,
               nvl(包装入库, 0) 包装入库,
               nvl(包装, 0) 包装
          from (SELECT WO_CODE AS WoCode, sum(USED_QTY) AS UsedQty
                  FROM T_SN2UPN
                 where (mat_code like ‘MFY%‘ OR mat_code like ‘EMBY%‘)
                   and MDATE >=
                       to_date(‘2014-04-27 08:30‘, ‘yyyy-mm-dd hh24:mi:ss‘)
                   AND MDATE <=
                       to_date(‘2014-04-28 08:30‘, ‘yyyy-mm-dd hh24:mi:ss‘)
                   and SUBSTR(TO_CHAR(MDATE + 30 / 1440, ‘YYYYMMDDHH24MISS‘),
                              9,
                              2) >= 9
                   AND SUBSTR(TO_CHAR(MDATE + 30 / 1440, ‘YYYYMMDDHH24MISS‘),
                              9,
                              2) < 21
                 group by Wo_Code) qx
          full join (select A.item_code,
                           A.wo_code,
                           C.PIXEL,
                           SUM(case
                                 when a.op_code = ‘DB‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) DB,
                           SUM(case
                                 when a.op_code = ‘WB后全检‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) WB,
                           SUM(case
                                 when a.op_code in
                                      (‘半成品组装‘, ‘组装LENS‘, ‘VCM封合‘) THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 成品站,
                           SUM(case
                                 when a.op_code = ‘H/M‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) HM,
                           SUM(case
                                 when a.op_code = ‘烘烤‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 烘烤,
                           SUM(case
                                 when a.op_code = ‘十级转出‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 十级产出,
                           SUM(case
                                 when a.op_code = ‘分粒接收‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 分粒接收,
                           SUM(case
                                 when a.op_code = ‘修边‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 分粒修边,
                           SUM(case
                                 when a.op_code = ‘马达焊接‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 焊接,
                           SUM(case
                                 when a.op_code = ‘打标‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 喷码打标,
                           SUM(case
                                 when a.op_code = ‘撕膜‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 撕膜,
                           SUM(case
                                 when a.op_code = ‘调焦‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 调焦,
                           SUM(case
                                 when a.op_code = ‘点螺纹胶及UV固化‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 点胶,
                           SUM(case
                                 when a.op_code = ‘点UV胶后全检胶量‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 点胶全检,
                           SUM(case
                                 when a.op_code = ‘功能测试‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 功测一,
                           SUM(case
                                 when a.op_code = ‘功能测试接收(修复)‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 功测接收修复,
                           SUM(case
                                 when a.op_code = ‘功能测试02‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 功测二,
                           SUM(case
                                 when a.op_code = ‘QC功能检‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) QC功测,
                           SUM(case
                                 when a.op_code = ‘远焦烧录‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 远焦烧录,
                           SUM(case
                                 when a.op_code = ‘近焦烧录‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 近焦烧录,
                           SUM(case
                                 when a.op_code = ‘OTP烧录‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) OTP烧录,
                           SUM(case
                                 when a.op_code = ‘OTP检测‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) OTP检测,
                           SUM(case
                                 when a.op_code = ‘QC OTP检测‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) QCOTP烧录,
                           SUM(case
                                 when a.op_code = ‘贴背胶‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 背胶,
                           SUM(case
                                 when a.op_code = ‘外观检查‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 外观,
                           SUM(case
                                 when a.op_code = ‘O/S测试‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) OS测试,
                           SUM(case
                                 when a.op_code = ‘CCD检验‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) CCD检验,
                           SUM(case
                                 when a.op_code = ‘贴膜‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 贴膜,
                           SUM(case
                                 when a.op_code = ‘修复维修‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 修复维修,
                           SUM(case
                                 when a.op_code = ‘脏点测试‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 脏点测试,
                           SUM(case
                                 when a.op_code = ‘修复焊接‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 修复焊接,
                           SUM(case
                                 when a.op_code = ‘修复修边‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 修复修边,
                           SUM(case
                                 when a.op_code = ‘修复调焦‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 修复调焦,
                           SUM(case
                                 when a.op_code = ‘修复功能测试‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 修复功能测试,
                           SUM(case
                                 when a.op_code = ‘修复功能测试‘ THEN
                                  OK_QTY
                                 ELSE
                                  0
                               END) 修复转出
                      from t_resume a, i_material c
                     WHERE a.item_code = c.part_code
                       AND (a.rcard, a.op_code, a.actionseq) in
                           (select rcard, op_code, max(actionseq) actionseq
                              from t_resume
                             where MDATE >=
                                   to_date(‘2014-04-27 08:30‘,
                                           ‘yyyy-mm-dd hh24:mi:ss‘)
                               AND MDATE <=
                                   to_date(‘2014-04-28 08:30‘,
                                           ‘yyyy-mm-dd hh24:mi:ss‘)
                             group by rcard, op_code)
                       AND A.WO_CODE = ‘MN1-14040158‘
                    
                     GROUP BY A.ITEM_CODE, A.WO_CODE, C.PIXEL
                    
                    ) gxcl
            on qx.WoCode = gxcl.wo_code
        
          full join (select substr(rcard, 1, 12) wo_code,
                           sum(case
                                 when (IS_PACKING = 1 and
                                      a.PACKING_DATE >=
                                      to_date(‘2014-04-27 08:30‘,
                                               ‘yyyy-mm-dd hh24:mi:ss‘) AND
                                      a.PACKING_DATE <=
                                      to_date(‘2014-04-28 08:30‘,
                                               ‘yyyy-mm-dd hh24:mi:ss‘)) and
                                      SUBSTR(TO_CHAR(a.PACKING_DATE + 30 / 1440,
                                                     ‘YYYYMMDDHH24MISS‘),
                                             9,
                                             2) >= 9 AND
                                      SUBSTR(TO_CHAR(PACKING_DATE + 30 / 1440,
                                                     ‘YYYYMMDDHH24MISS‘),
                                             9,
                                             2) < 21 then
                                  used_qty
                                 else
                                  0
                               end) 包装,
                           sum(case
                                 when (IS_BZTOSTOCK = 1 and
                                      a.BZTOSTOCK_DATE >=
                                      to_date(‘2014-04-27 08:30‘,
                                               ‘yyyy-mm-dd hh24:mi:ss‘) AND
                                      a.BZTOSTOCK_DATE <=
                                      to_date(‘2014-04-28 08:30‘,
                                               ‘yyyy-mm-dd hh24:mi:ss‘)) and
                                      SUBSTR(TO_CHAR(a.BZTOSTOCK_DATE + 30 / 1440,
                                                     ‘YYYYMMDDHH24MISS‘),
                                             9,
                                             2) >= 9 AND
                                      SUBSTR(TO_CHAR(BZTOSTOCK_DATE + 30 / 1440,
                                                     ‘YYYYMMDDHH24MISS‘),
                                             9,
                                             2) < 21 then
                                  used_qty
                                 else
                                  0
                               end) 包装入库
                      from (select *
                              from T_CARTON
                             where status IS NULL
                               and workshop_code = ‘生产二区‘) a
                     inner join t_carton2SN b
                        on a.carton_no = b.carton_no
                       AND ((a.BZTOSTOCK_DATE >=
                           to_date(‘2014-04-27 08:30‘,
                                     ‘yyyy-mm-dd hh24:mi:ss‘) AND
                           a.BZTOSTOCK_DATE <=
                           to_date(‘2014-04-28 08:30‘,
                                     ‘yyyy-mm-dd hh24:mi:ss‘)) OR
                           (a.PACKING_DATE >=
                           to_date(‘2014-04-27 08:30‘,
                                     ‘yyyy-mm-dd hh24:mi:ss‘) AND
                           a.PACKING_DATE <=
                           to_date(‘2014-04-28 08:30‘,
                                     ‘yyyy-mm-dd hh24:mi:ss‘)))
                     group by substr(rcard, 1, 12)) bz
            on gxcl.wo_code = bz.wo_code
        
          full join
        
         (select wo_code, sum(ng_qty) 修复接收
           from QTMR01
          where MDATE >=
                to_date(‘2014-04-27 08:30‘, ‘yyyy-mm-dd hh24:mi:ss‘)
            AND MDATE <=
                to_date(‘2014-04-28 08:30‘, ‘yyyy-mm-dd hh24:mi:ss‘)
            and SUBSTR(TO_CHAR(MDATE + 30 / 1440, ‘YYYYMMDDHH24MISS‘), 9, 2) >= 9
            AND SUBSTR(TO_CHAR(MDATE + 30 / 1440, ‘YYYYMMDDHH24MISS‘), 9, 2) < 21
          group by wo_code) xiufujieshou
            on xiufujieshou.wo_code = gxcl.wo_code) jieguo
 inner join i_wo allwo
    on allwo.wo_code = jieguo.wocode
 inner join i_material M
    on m.part_code = allwo.item_code
 where 1 = 1
   and allwo.workshop_code = ‘生产二区‘
 group by rollup(item_code, allwo.workshop_code, wo_code)


该sql是 olap 的, 在oracle10g 上面跑。跑一次要33秒钟,一般olap报表,最好的客户体验要在5秒以内。

大家注意看,sql里面有full join,在oracle10g里面,full join默认会扫描2次,一次left join 一次right join 然后union all. 这样肯定慢了。在11g 只扫描1次。

10g 里面可以用 一个hint  /*+ NATIVE_FULL_OUTER_JOIN */ ,让他们扫描1次

加了hint之后,SQL 3秒能出结果,她还问能否进一步优化,因为要讲课了,8点半讲课,没啥时间,明天帮忙看吧。

注意,这个hint别放在 第一个select 后面,这样是没用的。要放在 from (select /*+ NATIVE_FULL_OUTER_JOIN */  COALESCE(wocode,

也就是说要离full join 最近的一个 select 。至于为什么,请自己 google query block 关键字, hint一般只在 query block 生效。