两句SQL语句就这一点不同,为什么第二条就不行呢?请教SQL语句原理,还请众兄弟帮忙(100分)

S

SanDao

Unregistered / Unconfirmed
GUEST, unregistred user!
兄弟我今日在试验一个SQL语句!目的是取数据库中间的一些记录!(下面的例子是取11-20条记录)
于是兄弟我是这样写的:
SELECT TOP 10 * FROM Table
WHERE (ID_Field NOT IN
(SELECT TOP 10 ID_Field
FROM Table
WHERE CangKu = '库1' order by ID_Field)) AND (CangKu = '库1')
order by ID_Field
这样写原已满足我的要求!好了!数据也是对的!
--------------
于是我想搞的更好看一点!在里面想再按照ShengChanPH排序!就这样写
SELECT TOP 10 * FROM Table
WHERE (ID_Field NOT IN
(SELECT TOP 10 ID_Field
FROM Table
WHERE CangKu = '库1' order by ShengChanPH, ID_Field)) AND (CangKu = '库1')
order by ShengChanPH,ID_Field
运行!不好,SQLServer不动了,再看CPU100%,天哪,在做什么呢!过了一会,超时!
------------------
再试了一会儿,还是不行!无意中将 CangKu = '库1'删除!
SELECT TOP 10 * FROM Table
WHERE (ID_Field NOT IN
(SELECT TOP 10 ID_Field
FROM Table
order by ShengChanPH, ID_Field))
order by ShengChanPH,ID_Field
不加这个条件居然成功了!这样一来我好像明白了什么!Not In ,把条件CangKu = '库1'
也排除了!在外面的SQL语句当然没法查了!有可能是这样(CPU100%就不明白了,
现在已经很迷茫了)!
那为什么上面写的第一个SQL语句,我也这样写为什么就对了呢!(完全糊涂了!)
--------------------------
写的有点乱,不过估计大家能够看懂!忙我想想!谢谢!
 
SELECT TOP 10 * FROM Table
WHERE CangKu = '库1'
and (ID_Field NOT IN
(SELECT TOP 10 ID_Field
FROM Table
WHERE CangKu = '库1' order by ShengChanPH, ID_Field))
order by ShengChanPH,ID_Field
 
同意SMALLBS的提法!比较清晰!
 
>>smallbs
你写的和我写的第二段CPU100%的有什么区别?
好像只不过把 And 两边的条件互换了一下位置!
>>luckywzy
和我写的一样的呀!CPU100%,然后超时!你不信可以试一下!

麻烦两位再看看!
 
order by ID_Field, ShengChanPH
 
>>ugvanxk
倒过来是对的,不出错的,我早试过了!
但是,我要的就是不能倒呀!我要先ShengChanPH,再ID_Field的呀!:(
为什么这样就了错呢!CPU居然还100%! :(

大家帮忙啊!
 
哈哈! 楼主的写法没错,应该只是超时,不会出错,
把第二个order by ShengChanPH, ID_Field拿掉,速度会好些
 
in 使用的匹配方法很耗内存和cpu空间。建议不要使用——好像是废话?
你使用第一种方式限制条件不算太多,所以耗时勉强可以。后一种就是严重耗费计算机时间的了。
只能理解到这。看你的语法从表面上是没有问题的。
 
>>smallbs
是啊是啊,不出错,是超时!
第一个order by 是为了取值时和第二个order by 统一!
(第二个order by 是显示给用户看的,不能去的呀)

有没有解决的办法呀!...对了,为什么呀!(今天头有点大)
 
>>yzhshi
谢谢关注!
in也许的确很耗内存和cpu空间,但是我用这个方法在6万条记录中取第55000到55010的记录
时,速度很快,只有几十个毫秒!

我还用过其它的几个方法!比如用倒排序的方法,
Select Top 10 *
from (select top 30 * from Table order by ID_table) as aa
Order by ID_table Desc

但是大数据量的倒排序比我这个方法,在取几百后的数据时要比我慢一倍!
(大数据量的倒排序有点慢)

当然我对这个倒排序的方法进行了改进!不用From :(拿Customers表举例)
select * from(select top 100 *
from customers
where ID_Customer in (select top 61000 ID_Customer
from customers
Order by id_Customer)
order by id_customer desc ) as AA
order by id_customer
出错,但是数字小于31000不出错,61000就肯定出错了!
我在SQL语句后加了option(merge join)不出错了!不过暂时还没有明白为什么!

>>yzhshi兄,smallbs兄
如果我想满足这个要求,还能有其它的什么办法吗!顺便帮我解释解释,我对
SQL原理并不十分清楚!再次谢谢了!
 
我要走了,明天早上再来!对于大家的帮助!我再说声谢谢!
 
我认为应该建立索引 ShengChanPH, ID_Field,CangKu
或者用SQL SERVER 的查询分析器看看键什么INDEX
 
这两条sql等价吗?
第一个是按照ID_Field排序
第二个是按照ShengChanPH排序
 
原因大概是这样的
如果用top的同时用order by,就需要把所有的记录都选出来,然后再返回前N条,这样、
not in运算就会先得到一个很大的结果集
用SET ROWCOUNT 可能会好一些
 
我想建立索引可以解决(速度)
 
想一想:不要在(取 N次 记录的) N次 上做文章,可以在 上次记录的ID_table的最大值 上做文章。
--- ----------------------------
Select Top 10 *
from (select top 20 ID_table,field1_table,field2_table,... from Table
where ID_table>lastid order by ID_table) as aa
Order by ID_table Desc
其中 lastid 就是上次 Top 10 的(字段)ID_table 的最大值。
field1_table,field2_table... 用来取代 *,避免把不用的字段内容取出来而增加CPU负担。

如果一定要在 取N次 上做文章,可以考虑先用存储过程取得lastid的值,再用上面的SQL语句
来处理,或者全部放在存储过程里处理之。
 
>>smallbs兄
不好意思,昨天没空上来回贴!
你的思路是对的,但是我加上了ShengChanPH的排序,ID号的顺序是乱的呀,没法用
大于 上次取到的最大ID号来做!

所以我还是只能用ID号的唯一性来作文章!
对了,我的问题基本已解决了,用的是我上面写的最后一种方法!
(速度还是可以的,如果大家以后要有这样的用法,此法我推荐一试,当然如果只有
要用ID号来排序,大家还是用smallbs兄的方法更合理)
经高人指点在SQL语句后加了option(merge join),否则第二个Top超过30000就出错!
只是到现在还是对这个option(merge join)没有太明白!还望诸位解释一下!谢谢!
 
>>mtj,沉香屑,Pipi.
大家说的没错,索引是一定要建的!谢谢大家!
(不过还是超时!)
 
join就是把多个关系合并成一个关系
这些关系中一般都有相同的字段
一般的join做法是循环比较这些字段的值是否相等
但是如果这些字段是已经排序的话
就可以直接合并关系
这种join就叫做 merge join
 
>>沉香屑
听上去这样应该更快,但是我加上这个merge join要比不加慢一些,为什么呀!
而且为什么不加merge join超过一定记录就会出错呢!?
请教了,谢谢!
 
顶部