Sql语句优化问题
两个表:应该费用(客户号,金额)
实际费用(客户号,金额)
两个表中的客户号都有可能有0到多条记录
另外有客户表:客户(客户号,.....)
需要找到欠费的客户号,及实际费用表中的金额和小于应该费用表中的金额和
我写的Sql:
select 客户号 from 客户
where nvl((select sum(金额) from 应该费用 where 客户号 = 客户.客户号),0)-nvl((select sum(金额) from 实际费用 where 客户号 = 客户.客户号),0)>0
速度非常慢,请教优化方法
问题点数:100、回复次数:18Top
1 楼oldwain(老斗)回复于 2002-04-17 17:03:06 得分 0
另一种写法. 至于性能是否好, 需要你自己测试.
select z.客户号
from 应该费用 x, 实际费用 y, 客户 z
where z.客户号 = x.客户号 (+)
and z.客户号 = y.客户号 (+)
and nvl(sum(x.金额),0) > nvl(sum(y.金额),0);
===========================
oldwain
---------------------------
http://www.itpub.net/index.php?referrerid=32
http://www.linuxforum.net/forum/postlist.php?Cat=&Board=oracle
http://www.oraclefan.net/
下载 ITPUB免费电子杂志:
http://www.itpub.net/forumdisplay.php?s=32&forumid=9
Top
2 楼g_yxh()回复于 2002-04-17 17:31:00 得分 0
我试了一下,不行的,sum不能用在条件中 :-(Top
3 楼jornk(咸鱼)回复于 2002-04-17 18:04:04 得分 0
另一种写法. 至于性能是否好, 需要你自己测试.
select z.客户号
from 应该费用 x, 实际费用 y, 客户 z
group by z.客户号
having nvl(sum(x.金额),0) > nvl(sum(y.金额),0);
(不好意思,没测试过)Top
4 楼KingSunSha(弱水三千)回复于 2002-04-17 18:14:56 得分 80
我觉得这样应该效率比较高,省去了两个嵌套:
select 客户号, sum(金额) balance from
(select 客户号, 金额 from 应该费用
union all
select 客户号, -金额 from 实际费用)
group by 客户号
having sum(金额) > 0;
Top
5 楼mashansj(风影)回复于 2002-04-17 18:25:08 得分 5
先建两个视图
create view v_1
as
select x.客户号,sum(nvl(x.金额))
from 应该费用 x
group by x.客户号
create view v_2
as
select y.客户号,sum(nvl(y.金额))
from 实际费用 y
group by y.客户号
根据这两个视图求值应该会快点的Top
6 楼mr9(mr9)回复于 2002-04-17 22:03:53 得分 10
如果你经常遇到这样的问题,我建议你使用现成的第三方应用软件来解决此类关于优化问题。这样的软件有很多。比如著名的CA公司就有很好的产品,你可以到他们的网站看一下Top
7 楼jimsuker(Fish)回复于 2002-04-17 22:36:32 得分 5
用实例化视图Top
8 楼smartdonkey(聪明的毛驴)回复于 2002-04-17 23:55:43 得分 0
select 客户号 from
(select 客户号,sum(金额) 金额 from 应付费用) a left join
(select 客户号,sum(金额) 金额 from 实付费用) b
on a.客户号=b.客户号 where a.金额 >isnull(b.金额 ,0)
Top
9 楼KingSunSha(弱水三千)回复于 2002-04-18 09:19:36 得分 0
我觉得这个问题还是如我前面所写的union all的效果最好,假定两个表各有1万条记录,那用union all不过是处理2万条记录的group by,而其他的写法要处理10000*10000的nested loop,而且同样要group by,数据库处理2万行比处理两个1万行表的join当然要快得多。
Top
10 楼jornk(咸鱼)回复于 2002-04-18 09:44:47 得分 0
请楼主测一下这些写法,并请给出测试结果!Top
11 楼oldwain(老斗)回复于 2002-04-18 09:58:04 得分 0
不拿实例测, 就写不出像样的语句了.
竟然胡涂的连where sum() ...这样的语句都能写出来!
sorry!Top
12 楼g_yxh()回复于 2002-04-18 12:50:59 得分 0
测试结果:
select 客户号 from 客户 where nvl((select sum(金额) from 应该费用 where 客户号 = 客户.客户 号),0)-nvl((select sum(金额) from 实际费用 where 客户号 = 客户.客户 号),0)>0
2分26秒
select z.客户号 from 应该费用 x, 实际费用 y, 客户 z group by z.客户号 having nvl(sum(x.金额),0) > nvl(sum(y.金额),0)
运行后很久没有反应
select 客户号, sum(金额) balance from (select 客户号, 金额 from 应该费用 union all select 客户号, -金额 from 实际费用) group by 客户号having sum(金额) > 0;
671毫秒
Top
13 楼KingSunSha(弱水三千)回复于 2002-04-18 13:28:27 得分 0
我的测试结果:
* 两个表中各有1000万条记录,平均分布,客户号1万个
* select a.cust_id
from cust_id,
(select cust_id,sum(amount) x from tbl1 group by cust_id) a,
(select cust_id,sum(amount) y from tbl2 group by cust_id) b
where cust_id.cust_id = a.cust_id(+)
and cust_id.cust_id=b.cust_id(+)
and x < y;
返回时间为4.917s
* select cust_id
from (select cust_id, sum(amount) x from tbl1 group by cust_id
union all
select cust_id, sum(-amount) x from tbl2 group by cust_id)
group by cust_id
having sum(x)< 0;
返回时间5.131s
* 很难确定那种写法更好,还是根据实测结果来确定吧,不同的数据量、不同的数据分布有不用结果。Top
14 楼KingSunSha(弱水三千)回复于 2002-04-18 13:29:48 得分 0
写错了,两个表中各有100万纪录Top
15 楼blackwh()回复于 2002-04-18 14:03:34 得分 0
请问一下:KingSunSha(弱水三千)
sql这些知识在一般的sqls书中都有提及马?非常想提高自己的知识Top
16 楼g_yxh()回复于 2002-04-18 14:21:11 得分 0
非常感谢各位,最后我用的是
select 客户号, sum(金额) balance from
(select 客户号, 金额 from 应该费用
union all
select 客户号, -金额 from 实际费用)
group by 客户号 having sum(金额) > 0
这样在我的库里是最快的Top
17 楼g_yxh()回复于 2002-04-18 14:25:21 得分 0
非常感谢各位,最后我用的是
select 客户号, sum(金额) balance from
(select 客户号, 金额 from 应该费用
union all
select 客户号, -金额 from 实际费用)
group by 客户号 having sum(金额) > 0
这样在我的库里是最快的Top
18 楼KingSunSha(弱水三千)回复于 2002-04-18 14:25:53 得分 0
书上应该都有,但是我很少有工夫从头到尾仔细看,大部分经验是从实际中得到的,遇到问题的时候多查书。Top
19 楼blackwh()回复于 2002-04-19 10:50:02 得分 0
xiexieTop




