谁能帮我优化一下这个SQL语句,执行长达十几分种,太慢了。 ( 积分: 50 )

  • 主题发起人 主题发起人 无头骑士
  • 开始时间 开始时间

无头骑士

Unregistered / Unconfirmed
GUEST, unregistred user!
select QCBH,KHBH,KHMC,yjdf+SJDF as SJDF,JSDF,JYYE
,(jsdf-(select sum(sjdf)
from POWER.zw_dfsj a
where a.ssny=:ad_ssny
and a.dwbh=:as_dwbh and sfbz<>'6'
and a.sjlb='2' and a.khbh=b.khbh
group by qcbh,khbh,ssny)) as KDS
from POWER.zw_dfsj b
where b.ssny=:ad1_ssny
and b.dwbh=:as1_dwbh
AND B.SJLB='2'
and ( nvl((SELECT sum(JYYE) FROM power.ZW_DFSJ
WHERE KHBH=B.KHBH AND SYYESJBH=B.SJBH and sjlb='2' AND SFBZ NOT IN ('4','6','9','b')),0)>0
or ((jsdf-(select sum(sjdf)
from POWER.zw_dfsj a
where a.ssny=:ad2_ssny
and a.dwbh=:as2_dwbh and sfbz<>'6'
and a.sjlb='2' and a.khbh=b.khbh
group by qcbh,khbh,ssny)))>0
)
order by B.qcbh,b.khbh
 
select QCBH,KHBH,KHMC,yjdf+SJDF as SJDF,JSDF,JYYE
,(jsdf-(select sum(sjdf)
from POWER.zw_dfsj a
where a.ssny=:ad_ssny
and a.dwbh=:as_dwbh and sfbz<>'6'
and a.sjlb='2' and a.khbh=b.khbh
group by qcbh,khbh,ssny)) as KDS
from POWER.zw_dfsj b
where b.ssny=:ad1_ssny
and b.dwbh=:as1_dwbh
AND B.SJLB='2'
and ( nvl((SELECT sum(JYYE) FROM power.ZW_DFSJ
WHERE KHBH=B.KHBH AND SYYESJBH=B.SJBH and sjlb='2' AND SFBZ NOT IN ('4','6','9','b')),0)>0
or ((jsdf-(select sum(sjdf)
from POWER.zw_dfsj a
where a.ssny=:ad2_ssny
and a.dwbh=:as2_dwbh and sfbz<>'6'
and a.sjlb='2' and a.khbh=b.khbh
group by qcbh,khbh,ssny)))>0
)
order by B.qcbh,b.khbh
 
超级变态,不要优了(维护要死人的),最好写个存储过程,功能分开写(那怕用临时表)。
 
放到存储过程里实现好点。
 
这是客户端传的语句,要到服务器程序才能运行,和是否为存储过程没有关系的。
 
你客户端为什么要传语句?难道不能传参数让服务器的Proc执行吗?!
你这样嵌套太多当然很慢了。另外用Proc效率高的多,毕竟是在服务器端执行。
 
我的程序是PB+JAVA+WEBLOGIC+ORACLE的。。。
我从PB端传这个语句到JAVA,然后JAVA调ORACLE的,如果我把语句放在JAVA端,PB端传参数,效果也是一样的。
这是一个省电力公司的交费记录表,里面记录数据可想而知,所以关键关不是传输上的问题,而是查询时用的时间太长了。
 
那就重新分析你要什么结果,重新写语句!
关键是谁知道你那个语句要什么,还谈什么优化?!
SFBZ NOT IN --> NOT SFBZ IN
 
仔细想想,我还是坚持最开始的说法。
你从PB端传参数到JAVA,然后JAVA调ORACLE的Proc...
反正你要的是结果集,用proc不用向你这样写成一团(一段一段的可以写的很明白,可以用临时表(不用嵌套这么多))。

另外你把要查的表结构贴上来,让别人帮你重新写个撒,这样谁也帮不上你的忙!
 
最好写个存储过程用一下#temp
 
收据编号(SJBH) 客户编号(KHBH) 总电量(ZDL) 应收电费(YSDF) 其中预付电费(JZYFDF) 结算电费(JSDF) 已交电费(YJDF) 实交电费(SJDF) 结余额(JYYE) 所属年月(SSNY) 。。。。。
其中主键盘:收据编号
索引:收据编号 客户编号 所属年月

这里查的就是扣多收,意思是扣上次的预付,这里只是扣了部分,预付就为0,或者是没有扣,又收了费,所以结余额大于0

select QCBH,KHBH,KHMC,yjdf+SJDF as SJDF,JSDF,JYYE
,(jsdf-(select sum(sjdf) //这里用SUM是因为客户可能会分多次交当月的电费,JSDF是结算电费,SJDF是实交电费,所以结算电费减去所有实交电费的合计就是扣了预额金额
from POWER.zw_dfsj a
where a.ssny=to_date('2005-10','yyyy-mm')
and a.dwbh='060101' and sfbz<>'6'
and a.sjlb='2' and a.khbh=b.khbh and a.qcbh=b.qcbh and a.ssny=b.ssny
group by qcbh,khbh,ssny)) as KDS
from POWER.zw_dfsj b
where b.ssny=to_date('2005-10','yyyy-mm')
and b.dwbh='060101'
AND B.SJLB='2'
and (
nvl((SELECT sum(JYYE) FROM power.ZW_DFSJ
WHERE KHBH=B.KHBH AND SYYESJBH=B.SJBH and sjlb='2' AND SFBZ NOT IN ('4','6','9','b')),0)>0 // 1 这里要看如果结余余额大于0,可能上次扣了部分,而又实交又多出结余额
or
((jsdf-(select sum(sjdf) //这里上面1的或才能求出所有的记录。
from POWER.zw_dfsj a
where a.ssny=to_date('2005-10','yyyy-mm')
and a.dwbh='060101' and sfbz<>'6'
and a.sjlb='2' and a.khbh=b.khbh and a.qcbh=b.qcbh and a.ssny=b.ssny
group by qcbh,khbh,ssny)))>0
)
order by B.qcbh,b.khbh
最后得出的结果是:
客户编号 结算电费 扣多收 实缴电费 结余余额。。。
 
问题解决。。。。。谢谢楼上的。
 
怎么解决的?我到过西宁的,而且你在四川好多地方干过啊,以后还要向你多学习,呵呵.
 
楼上的,你怎么知道我在四川多好地方干过啊?
解决问题:
select sum(sjdf)
from POWER.zw_dfsj a
where a.ssny=:ad_ssny
and a.dwbh=:as_dwbh and sfbz<>'6'
and a.sjlb='2' and a.khbh=b.khbh
group by qcbh,khbh,ssny)

把这些取掉了,
然后加了条件:把记录数据按日期最大的取出来,然后JSDF-YJDF-SJDF(结算电费-已交电-实交电费)
关键是想到最大日期就可以,不用再合计了.
 
后退
顶部