SQL语句效率太低,2万条数5分钟还没有查询出来...

wea1978 2006-04-29 11:29:05
这是昨天的问题:
但是速度太慢了...
select distinct a.[No], a.code, a.codename,a.nume,(case when a.nume = 0 then 0 when a.nume < b.nume then 0 else (a.nume - b.nume) * 1.0 / a.nume end) as 不良
from (select [No], code, codename , (isnull(Anumeric,0) + isnull(Bnumeric,0) + isnull(Cnumeric,0)) as nume from V_work) a
join (select [Lot No], code, codename, (isnull(Anumeric,0) + isnull(Bnumeric,0) + isnull(Cnumeric,0)) as nume from V_work) b
on b.code = (select min(code) from V_work where code > a.code)
where a.[No] in(select distinct [No] from v_work where stdate between '2006-04-01' and '2006-04-10')
order by a.[No], a.code

请各位大侠帮忙看看,谢谢!
那个V_work是个简单的视图,只是从一个表里取相应的字段而已,应该没什么问题...
...全文
897 41 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
41 条回复
切换为时间正序
请发表友善的回复…
发表回复
BurningM 2006-04-30
  • 打赏
  • 举报
回复
where a.[No] in(select distinct [No] from v_work where stdate between '2006-04-01' and '2006-04-10')
---------------------
不要使用in,这会大幅度下降sql效率
wea1978 2006-04-29
  • 打赏
  • 举报
回复
我的查询有问题:
现在用 Yang_(扬帆破浪) 的方法,共用去4分21秒,和dulei115()的方法使用的时间一样,结果也一样,服务器提示:
(5857 row(s) affected)
(5857 row(s) affected)
(1869253 row(s) affected)


请问有更好的方法吗?
wea1978 2006-04-29
  • 打赏
  • 举报
回复
不一定要用我的方式,呵呵...
我的方法也是dulei115() 朋友提供的
我只想以最快的方法得到结果...
rouqu 2006-04-29
  • 打赏
  • 举报
回复
连接的两个表都是相同的视图 楼主可以考虑能不能直接在一张表里进行处理
上面这个连接条件能不能理解成两个相同的视图之间做纪录对应 条件是隔行对应?
rouqu 2006-04-29
  • 打赏
  • 举报
回复
....
on b.code = (select min(code) from V_work where code > a.code)
....

楼主能否解释一下这句话?看不明白
Yang_ 2006-04-29
  • 打赏
  • 举报
回复
尾巴:

drop table #a
drop table #b

wea1978 2006-04-29
  • 打赏
  • 举报
回复
可以直接对v_work表调用,但也是一样...因为v_work表只是个查询视图而已,
select [No], code, codename ,Anumeric,Bnumeric,Cnumeric,stdate from work
Yang_ 2006-04-29
  • 打赏
  • 举报
回复
临时表:

select [No], code, codename , (isnull(Anumeric,0) + isnull(Bnumeric,0) + isnull(Cnumeric,0)) as nume
into #a
from V_work
where stdate between '2006-04-01' and '2006-04-10'

select [Lot No], code, codename, (isnull(Anumeric,0) + isnull(Bnumeric,0) + isnull(Cnumeric,0)) as nume
into #b
from V_work --怎么没有where ?最好限定下


select distinct a.[No], a.code, a.codename,a.nume,(case when a.nume = 0 then 0 when a.nume < b.nume then 0 else (a.nume - b.nume) * 1.0 / a.nume end) as 不良
from #a a
join #b b
on b.code = (select min(code) from V_work where code > a.code)

--where a.[No] in(select distinct [No] from v_work where stdate between '2006-04-01' and '2006-04-10') --这个where 没有必要了

order by a.[No], a.code
wea1978 2006-04-29
  • 打赏
  • 举报
回复
用临时表也可以,主要是能够得出结果,并且速度可以接受...
比如上面的查询得出来的结果应该是:
[No], code, codename ,Anumeric,Bnumeric,Cnumeric,stdate ,不良
001 , 1 , products , 1000 , 0 , 0 , 2006-04-01,0
001 , 2 , products , 990 , 0 , 0 , 2006-04-01,0.01
001 , 3 , products , 990 , 0 , 0 , 2006-04-02,0
001 , 4 , products , 980 , 0 , 0 , 2006-04-02,0
001 , 5 , products , 0 , 0 , 0 , 2006-04-04,0
001 , 6 , products , 980 , 0 , 0 , 2006-04-04,0
但如果code=6的数是970的话,它的不良就不是0了.而是(980-970)/980..同样code=4的时候也是,一直往下找,直到找不到比自己大的状态,就为0...,状态是固定最多7个,
WangZWang 2006-04-29
  • 打赏
  • 举报
回复
那你V_work的语句是什么?可不可以直接对work表调用?
wea1978 2006-04-29
  • 打赏
  • 举报
回复
要的结果就是对work表操作:
work表有字段:
[No], code, codename ,Anumeric,Bnumeric,Cnumeric,stdate
001 , 1 , products , 1000 , 0 , 0 , 2006-04-01
001 , 2 , products , 990 , 0 , 0 , 2006-04-01
001 , 3 , products , 990 , 0 , 0 , 2006-04-02
001 , 4 , products , 980 , 0 , 0 , 2006-04-02
001 , 5 , products , 0 , 0 , 0 , 2006-04-04
001 , 6 , products , 980 , 0 , 0 , 2006-04-04

要在此基础上得出每个code状态的不良,总共有7个状态,第1个和第7个状态的不良为0,
code=2的不良数是(1000-990)/1000,每个阶段都一样的做法,并且要排除数据为0或者下个阶段数据比上个阶段更多的情况...
刚才dulei115() 的方法查询出的数据有几百万条,而实际数只有1,2万或更少...
xeqtr1982 2006-04-29
  • 打赏
  • 举报
回复
可不可以把那段时间的记录取出来into到临时表,然后对临时表进行操作。
wea1978 2006-04-29
  • 打赏
  • 举报
回复
索引不能建,因为别人的数据库,所以只能在查询语句上作优化...
WangZWang 2006-04-29
  • 打赏
  • 举报
回复
首先要看你要得到什么样的结果,根据要求来写sql
单从你的sql不好写出更优化的sql.
dulei115 2006-04-29
  • 打赏
  • 举报
回复
这样
select distinct a.[No], a.code, a.codename,a.nume,
(case when a.nume = 0 then 0 when a.nume < b.nume then 0 else (a.nume - b.nume) * 1.0 / a.nume end) as 不良
from (select [No], code, codename , (isnull(Anumeric,0) + isnull(Bnumeric,0) + isnull(Cnumeric,0)) as nume from V_work
where stdate between '2006-04-01' and '2006-04-10') a
join (select [Lot No], code, codename, (isnull(Anumeric,0) + isnull(Bnumeric,0) + isnull(Cnumeric,0)) as nume from V_work) b
on b.code = (select min(code) from V_work where code > a.code)
order by a.[No], a.code
如果还是不行,就建code字段的索引
wea1978 2006-04-29
  • 打赏
  • 举报
回复
谢谢楼上...游标运行没有问题了...
谢谢各位朋友热情回复,再次感谢!
我对SQL掌握的还不够,还请各位大侠多多指教!
wea1978 2006-04-29
  • 打赏
  • 举报
回复
奇怪,我在在查询的条件后面加多个条件 and a.num<>b.num,
服务器还是提示:
Server: Msg 8134, Level 16, State 1, Line 25
Divide by zero error encountered.
The statement has been terminated.
skywebnet 2006-04-29
  • 打赏
  • 举报
回复
bl=case when a.num<>0 then (a.num-b.num)/a.num else 0 end
wea1978 2006-04-29
  • 打赏
  • 举报
回复
谢谢楼上各位...
skywebnet(小苯)的结果还是不正确...
谢谢了!看来我还是用那个游标了...但游标也会出问题
就是有条数据结果会为0,就出错了...
skywebnet 2006-04-29
  • 打赏
  • 举报
回复
^-^ ,只要能按要求实现就OK了
加载更多回复(21)

22,302

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧