本例是一个UPDATE语句,据说要20多分钟才行完成
UPDATE tablel f
SET f.累计金额1 =
(SELECT mvl(SUM(nvl(b.金额1,0)),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.会计期间,1,4) = substr(f.会计期间,1,4)),
f.金额2 =
(SELECT mvl(SUM(nvl(e.金额1,0)),0)
FROM table2 e
WHERE e.会计期间 <= f.会计期间
AND e.公司 = f.公司
AND e.部门 = f.部门
AND e.业务 = f.业务),
f.累计金额2 =
(SELECT mvl(SUM(nvl(e.金额1,0)),0)
FROM table2 e
WHERE e.会计期间 <= f.会计期间
AND e.公司 = f.公司
AND e.部门 = f.部门
AND e.业务 = f.业务
AND substr(e.会计期间,1,4) = substr(f.会计期间,1,4))
WHERE substr(f.会计期间,1,4) = 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.会计期间,1,4) = extract(YEAR FROM SYSDATE)
第二个子查询中,把关联列放在SELECT 和GROUP BY后面
SELECT e.公司,e.部门,e.业务,e.会计期间,SUM(金额1) AS 金额2
FROM table2e
WHERE substr(f.会计期间,1,4) = 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.会计期间,1,4) = 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.会计期间,1,4) = 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.会计期间,1,4) = extract(YEAR FROM SYSDATE))b ON (f.rowid=b.rid)
WHEN MATCH THEN
UPDATE
SET f.累计金额1 = nvl(b.累计金额1,0),
f.金额2 = nvl(b.金额2,0),
f.累计金额2 = nvl(b.累计金额2,0)
选自《Oracle 查询优化改写技巧与案例》 有教无类 落落 著