关联表更新Merge优化

昨天,有一位美女提出了如下需求,周末没事,在家里好好查了一下。

1 需求分析

有三张表,商品表(TBLITEM),库存表(TBLSTORAGE),库存管理表(TBLMANAGEMENT);

每一种商品对应的处理区分是0,并且库存总量大于1000,就把库存管理表的库存区分更新为1,小于1000,更新为0。

2 数据准备

DROP TABLE TBLITEM;

DROP TABLE TBLSTORAGE;

DROP TABLE TBLMANAGEMENT;

create table TBLITEM as  select d.OWNER as ITEMNO,round(dbms_random.value) as HANDLE_FLG from dba_objects d WHERE d.owner<>'sys';

create table TBLSTORAGE as select d.OWNER as ITEMNO,trunc(dbms_random.value(0,100)) as STROR_AMOUNT from dba_objects d WHERE d.owner<>'sys' ;

create table TBLMANAGEMENT as select d.OWNER as ITEMNO,round(dbms_random.value) as STORE_KIND from dba_objects d WHERE d.owner<>'sys' ;

3 SQL改善

3.1 写法一

UPDATE TBLMANAGEMENT M

SET M.STORE_KIND=(SELECT CASE WHEN SUM(S.STROR_AMOUNT)>1000 THEN 1

                         ELSE 0 END

                  FROM TBLITEM I

                                INNER JOIN TBLSTORAGE S

                                     ON I.ITEMNO=S.ITEMNO

                              WHERE I.HANDLE_FLG=0

                                AND M.ITEMNO=I.ITEMNO

                                   AND M.ITEMNO=S.ITEMNO

                              GROUP BY S.ITEMNO)

WHERE EXISTS (SELECT 1

              FROM TBLITEM I

                            INNER JOIN TBLSTORAGE S

                              ON I.ITEMNO=S.ITEMNO

                        WHERE I.HANDLE_FLG=0

                          AND M.ITEMNO=I.ITEMNO

                             AND M.ITEMNO=S.ITEMNO);

这种写法能够实现需求,但是作为资深的老牌强迫症患者,一条SQL语句中重复扫描一张表是不能忍受的,所以有了下面异想天开的写法。

 

3.2写法二(错误)

WITH TMP AS

    (SELECT S.ITEMNO, (CASE WHEN SUM(S.STROR_AMOUNT)>1000 THEN 1

                       ELSE 0 END) AS AMOUTFLG

     FROM TBLITEM I

           INNER JOIN TBLSTORAGE S

                 ON I.ITEMNO=S.ITEMNO

        WHERE I.HANDLE_FLG=0

        GROUP BY S.ITEMNO)

UPDATE TBLMANAGEMENT M

SET M.STORE_KIND=(SELECT T.AMOUTFLG

                  FROM TMP T

                              WHERE T.ITEMNO=M.ITEMNO)

WHERE EXISTS(SELECT 1

             FROM TMP T

                      WHERE T.ITEMNO=M.ITEMNO);

这条语句直接有语法错误,如果是检索处理,用with提取公共部分,还可以,但是是更新操作,无法实现。

3.3 Merge优化

MERGE INTO TBLMANAGEMENT M

  USING (SELECT S.ITEMNO, (CASE WHEN SUM(S.STROR_AMOUNT)>1000 THEN 1

                          ELSE 0 END) AS AMOUNT_FLG

         FROM TBLITEM I

                     INNER JOIN TBLSTORAGE S

                            ON I.ITEMNO=S.ITEMNO

               WHERE I.HANDLE_FLG=0

               GROUP BY S.ITEMNO) T

    ON (M.ITEMNO=T.ITEMNO)

WHEN MATCHED THEN UPDATE SET M.STORE_KIND=T.AMOUNT_FLG;

用merge改写,避免了表的重复的扫描,物理读有181k降低到75多。IO减少一半。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值