为什么sql server 2005中是先执行order by 再执行top??

liubo1977 2011-05-15 05:47:43
sql server 2005中是先执行order by 然后执行top,我感觉这种做法不合理,试想一下,如果一个表有几百万行,只提取前10行,如果先排序会花费很多时间,因为我只需要提取前10行,所以SQL Server的最优做法应该是:先提取10行,然后对这10排序,不知SQL Server为什么不这样做??
...全文
744 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
LongRui888 2013-11-24
  • 打赏
  • 举报
回复
引用 19 楼 liuhePPPP 的回复:
[quote=引用 18 楼 gdstfox 的回复:] 先排序后提取10行 select top 10 * from [class] order by grade 先提取10行后排序 select * from(select top 10 * from [class]) tmp order by grade 以上两种的结果是完全不一样的。
请教各位大神top语句的兼容性如何?经常用到吗?[/quote] 建议你少用top吧,sql server 2005有row_number函数,可以很轻松的实现,包括分页:
select *
from
(
	select *,
		   ROW_NUMBER() over(order by order by grade) as rownum
	from [class]  
)tmp 
where rownum <= 10
这个是分页的:


declare @page_size int;
declare @page_num int;

--比如:每页10条记录
set @page_size = 10;

--比如:先取第1页
set @page_num = 1;

select *
from
(
select *,   

       (row_number() over(order by grade) - 1) / @page_size as pagenum
from [class] 
)t
where pagenum = @page_num - 1
  • 打赏
  • 举报
回复
引用 18 楼 gdstfox 的回复:
先排序后提取10行 select top 10 * from [class] order by grade 先提取10行后排序 select * from(select top 10 * from [class]) tmp order by grade 以上两种的结果是完全不一样的。
请教各位大神top语句的兼容性如何?经常用到吗?
發糞塗牆 2013-11-21
  • 打赏
  • 举报
回复
不排序怎么知道如何定义“前n行”呢?除非你有聚集索引。如果没有聚集索引,表本身就没什么顺序,你的top只能是“随机”排序,得出来的不一定是你想要的
gdstfox 2013-11-21
  • 打赏
  • 举报
回复
先排序后提取10行 select top 10 * from [class] order by grade 先提取10行后排序 select * from(select top 10 * from [class]) tmp order by grade 以上两种的结果是完全不一样的。
siegebaoniu 2013-11-20
  • 打赏
  • 举报
回复
lz 你那情况 select * from (select top 10 * from class) order by 1 行不?
fancy0109 2011-05-18
  • 打赏
  • 举报
回复
你从1数到10,这么说: 1、2、3、4、5、6、7、8、9、10,你要是能完整数了,并理解这个顺序,在顺便理解一下 A、B、C、D、的顺序。你就啥都明白了。
bean_sql 2011-05-18
  • 打赏
  • 举报
回复
liubo1977 2011-05-18
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 jiao3630 的回复:]
因为sql 本身存储是的是一个无序集合
数据本身么有顺序
top 一般 都结合 order by 使用
单纯用top 的话结果是不确定的
所有先order by
[/Quote]
我上面实验的情况是随着数据量的增加,SQL Server对top和order by 执行的顺序不一样,这个如何解释?是SQL Server本身出了问题吗?
Spade_J 2011-05-16
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 liubo1977 的回复:]
引用 1 楼 qgqch2008 的回复:
假如你要查询班级排名前5名的人,how to ?

你这种情况可以这样写(假名班级表叫class,有一个列是名次,该列叫:grade):
select top 5 * from (select * from class order by grade) as a
[/Quote]

这么写应该会报错
laowang134 2011-05-16
  • 打赏
  • 举报
回复
你要知道表中的数据是一个集合本没有顺序的。你必须给它一个排序规则才能知道哪些是top ten
obuntu 2011-05-16
  • 打赏
  • 举报
回复
TOP出来的东西并不是排序好的,要想有排序,order by是少不了。

理解这个,也就知道为什么先order by 后 top 了。
fancy0109 2011-05-16
  • 打赏
  • 举报
回复
1、加不加order by,提取的时候都会有个序列;
2、使用top,必须有个基础,在某个基础(一个序列)上执行top操作;

你理解的先top然后再排序:
1、随机(默认排序)选取top(X);
2、在此基础上排序;

这和你提到的几百万条没有关系,速度不取决于order by 或者 top,而是where有的字段以及当前表的索引;再者,随机提取top似乎没有意义,你要是加了where条件还有几百万条的话,那你把这几百万条数据给谁看啊。

你说的sqlserver为什么不先top在order by,我可以这么回答你:猪,不管什么猪,它首先是个动物,这个猪多肥,是不是野猪,首先确定为动物,然后确认为猪,才能讨论。
jiao3630 2011-05-16
  • 打赏
  • 举报
回复
因为sql 本身存储是的是一个无序集合
数据本身么有顺序
top 一般 都结合 order by 使用
单纯用top 的话结果是不确定的
所有先order by
gogodiy 2011-05-16
  • 打赏
  • 举报
回复
首先要搞清基础概念:SQL的理论基础是集合论,可以把表看成是一个集合。集合中的行之间是没有预先定义的顺序的,它只是成员之间的一种逻辑组合,成员之间的顺序无关紧要。
而带有ORDER BY子句的查询,返回的不是一个集合,是一个对象,ANSI把这种对象称为游标(CURSOR),这个不是集合。
而针对你的需求,你要取前10行,这前10行如何来界定?难道没有任何规则就随便取前10行?那取出来的这前10行有什麽意义?如果没意义的话,取出来有什麽用呢?
liubo1977 2011-05-15
  • 打赏
  • 举报
回复
关于big_pubs数据库,大家可以到这里下载。
http://www.informit.com/content/images/9780672328244/cd-rom_fixes/CD.zip
下载之后解压,有一个Sample Databases目录,里面就有big_pubs数据库。
liubo1977 2011-05-15
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 mingpei0703 的回复:]
不先order by怎么知道哪些是前十行呢?
[/Quote]
这个你可以自己控制。如果你真的想要排好序的前10行,你可以写成这样:select top 5 * from (select * from class order by grade) as a
但是如果我只想要得取前10行,然后排序,那又如何写呢?我做了三条SQL语句做对比,其结果是对于同一个表,如果表的数据量不一样,得到的结果就不一样,结果让我感到非常奇怪。现将结果及实验顺序贴出来大家讨论。
我的三条sql是这样的:
select top 10 stor_id ,ord_date from sales
select * from (select top 10 stor_id ,ord_date from sales)as a order by a.ord_date
select top 10 stor_id ,ord_date from sales order by ord_date

当表sales的数据为21条时,即sales表为一般的pubs数据库表时,得到的结果为:
执行select top 10 stor_id ,ord_date from sales的结果。

6380 1994-09-14 00:00:00.000
6380 1994-09-13 00:00:00.000
7066 1993-05-24 00:00:00.000
7066 1994-09-13 00:00:00.000
7067 1994-09-14 00:00:00.000
7067 1992-06-15 00:00:00.000
7067 1992-06-15 00:00:00.000
7067 1992-06-15 00:00:00.000
7131 1994-09-14 00:00:00.000
7131 1994-09-14 00:00:00.000

执行select * from (select top 10 stor_id ,ord_date from sales)as a order by a.ord_date的结果。
7067 1992-06-15 00:00:00.000
7067 1992-06-15 00:00:00.000
7067 1992-06-15 00:00:00.000
7896 1993-02-21 00:00:00.000
8042 1993-03-11 00:00:00.000
8042 1993-05-22 00:00:00.000
7066 1993-05-24 00:00:00.000
7131 1993-05-29 00:00:00.000
7131 1993-05-29 00:00:00.000
7131 1993-05-29 00:00:00.000

执行select top 10 stor_id ,ord_date from sales order by ord_date的结果。

7067 1992-06-15 00:00:00.000
7067 1992-06-15 00:00:00.000
7067 1992-06-15 00:00:00.000
7896 1993-02-21 00:00:00.000
8042 1993-03-11 00:00:00.000
8042 1993-05-22 00:00:00.000
7066 1993-05-24 00:00:00.000
7131 1993-05-29 00:00:00.000
7131 1993-05-29 00:00:00.000
7131 1993-05-29 00:00:00.000

但是当然在另一个叫big_pubs的数据库中,执行上面的sql时,其sales表有168725行,此时得到的结果为:

扫行select top 10 stor_id ,ord_date from sales的结果为:

6380 1994-09-14 00:00:00.000
6380 1994-09-13 00:00:00.000
6380 1994-08-09 00:00:00.000
7066 1993-05-24 00:00:00.000
7066 1994-01-13 00:00:00.000
7066 1995-09-16 00:00:00.000
7066 1994-08-31 00:00:00.000
7066 1993-01-15 00:00:00.000
7066 1995-05-26 00:00:00.000
7066 1993-06-16 00:00:00.000
执行:select * from (select top 10 stor_id ,ord_date from sales)as a order by a.ord_date的结果为:

7066 1993-01-15 00:00:00.000
7066 1993-05-24 00:00:00.000
7066 1993-06-16 00:00:00.000
7066 1994-01-13 00:00:00.000
6380 1994-08-09 00:00:00.000
7066 1994-08-31 00:00:00.000
6380 1994-09-13 00:00:00.000
6380 1994-09-14 00:00:00.000
7066 1995-05-26 00:00:00.000
7066 1995-09-16 00:00:00.000

执行select top 10 stor_id ,ord_date from sales order by ord_date的结果为:

7067 1992-06-15 00:00:00.000
7067 1992-06-15 00:00:00.000
7067 1992-06-15 00:00:00.000
A031 1993-01-01 00:00:00.000
A196 1993-01-01 00:00:00.000
A215 1993-01-01 00:00:00.000
A946 1993-01-01 00:00:00.000
B357 1993-01-01 00:00:00.000
B376 1993-01-01 00:00:00.000
B453 1993-01-01 00:00:00.000
mingpei0703 2011-05-15
  • 打赏
  • 举报
回复
不先order by怎么知道哪些是前十行呢?
liubo1977 2011-05-15
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 qgqch2008 的回复:]
假如你要查询班级排名前5名的人,how to ?
[/Quote]
你这种情况可以这样写(假名班级表叫class,有一个列是名次,该列叫:grade):
select top 5 * from (select * from class order by grade) as a
liubo1977 2011-05-15
  • 打赏
  • 举报
回复
但如果我只想查询前询一个表的前5名,然后将这前5名排序,这又怎么做?
qgqch2008 2011-05-15
  • 打赏
  • 举报
回复
假如你要查询班级排名前5名的人,how to ?

22,209

社区成员

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

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