SQL优化和查询(十七)

本例是一个UPDATE语句,据说要20多分钟才行完成

UPDATE tablel  f 
   SET f.累计金额1 = 
      (SELECT mvl(SUM(nvl(b.金额10)),0)
         FROM table1 b 
         WHERE b.会计期间 <= f.会计期间
         AND b.公司 = f.公司
         AND b.部门 = f.部门
         AND b.业务 = f.业务
         AND b.currency_id = f.currency_id
         AND substr(b.会计期间,14) = substr(f.会计期间,14)),
      f.金额2 = 
       (SELECT mvl(SUM(nvl(e.金额10)),0)
         FROM table2 e 
         WHERE e.会计期间 <= f.会计期间
         AND e.公司 = f.公司
         AND e.部门 = f.部门
         AND e.业务 = f.业务),
      f.累计金额2 = 
      (SELECT mvl(SUM(nvl(e.金额10)),0)
         FROM table2 e 
         WHERE e.会计期间 <= f.会计期间
         AND e.公司 = f.公司
         AND e.部门 = f.部门
         AND e.业务 = f.业务         
         AND substr(e.会计期间,14) = substr(f.会计期间,14))
    WHERE substr(f.会计期间,14) = extract(YEAR FROM SYSDATE);

把主表与子里的语句一起放在USING子句里面,
1、第一个子查询除了等值条件外,还有一个条件(b.会计期间 <= f.会计期间),所以说是一个累加,用分析函数来处理
2、第二个子查询中有聚合函数,那就要先把关联条件放入GROUP BY 中,分组汇总,后再关联
3、第三个子查询与第二个类似,只是等值条件改成了(e.会计期间 <= f.会计期间),又是累加,用分析函数来处理
第一个子查询直接使用累加方法,同时把主查询的条件加进来

SELECT b.rowid AS rid,
        SUM(b.金额1) over (PARTITION BY b.公司,b.部门,b.业务,b.currency_id ORDER BY b.会计期间)AS 累计金额1
    FROM table1 b 
    WHERE substr(f.会计期间,14) = extract(YEAR FROM SYSDATE)

第二个子查询中,把关联列放在SELECT 和GROUP BY后面

SELECT e.公司,e.部门,e.业务,e.会计期间,SUM(金额1) AS 金额2
FROM table2e 
WHERE substr(f.会计期间,14) = extract(YEAR FROM SYSDATE)
GROUP BY  e.公司,e.部门,e.业务,e.会计期间;

对于上面的数据,再用分析函数累加,得到第三个子查询的数据,就可以少扫描一次 table2

SELECT e.公司,e.部门,e.业务,e.会计期间,e.金额2,
        SUM(金额2) over (PARTITION BY  e.公司,e.部门,e.业务 ORDER BY e.会计期间)AS 累计金额2
FROM (SELECT e.公司,e.部门,e.业务,e.会计期间,SUM(金额1) AS 金额2
        FROM table2e 
        WHERE substr(f.会计期间,14) = extract(YEAR FROM SYSDATE)
        GROUP BY  e.公司,e.部门,e.业务,e.会计期间)e

最后再用第一个子查询来关联上面这个结界集

MERGE INTO table f 
USING(SELECT b.rowid AS rid,
        SUM(b.金额1) over (PARTITION BY b.公司,b.部门,b.业务,b.currency_id ORDER BY b.会计期间)AS 累计金额1,
        e.金额2,
        e.累计金额2,        
    FROM table1 b 
    LEFT JOIN (SELECT e.公司,
                    e.部门,
                    e.业务,
                    e.会计期间,
                    e.金额2,
                    SUM(金额2) over (PARTITION BY  e.公司,e.部门,e.业务 ORDER BY e.会计期间)AS 累计金额2
                FROM (SELECT e.公司,
                            e.部门,
                            e.业务,
                            e.会计期间,
                            SUM(金额1) AS 金额2
                        FROM table2e 
                        WHERE substr(f.会计期间,14) = extract(YEAR FROM SYSDATE)
                        GROUP BY  e.公司,e.部门,e.业务,e.会计期间)e)e
            ON(e.会计期间 = b.会计期间 AND e.公司 = b.公司 AND e.部门 = b.部门 AND e.业务 = b.业务)
        WHERE substr(f.会计期间,14) = extract(YEAR FROM SYSDATE))b ON (f.rowid=b.rid)
WHEN MATCH THEN 
    UPDATE 
        SET f.累计金额1 = nvl(b.累计金额10),
            f.金额2 = nvl(b.金额20),
            f.累计金额2 = nvl(b.累计金额20)

选自《Oracle 查询优化改写技巧与案例》 有教无类 落落 著

猜你喜欢

转载自blog.csdn.net/every__day/article/details/77543374