从这个查询计划中大家可以清楚的看到
第一种扫描完zhuisuo表后先降序(top N Sort)然后在4行范围中取前2行
第二种扫描完zhuisuo表后先升序取4行(top N Sort)然后再把这4行降序取2行(top N Sort)
在这里就不得不简单的说说SQL语句中出现的表子查询了
表子查询,而出现在from子句中的表我们称为派生表
派生表是虚拟的,未被物理具体化,也就是说当编译的时候
如(select top 2 * from (select top 4 * from zhuisuo) m order by m.id desc )
外部查询和内部查询会被合并,并生成一个计划
这时再看看上面的执行计划就一目了然了
(注意事项:在派生表里面一般不允许使用order by除非指定了top
也就是说select top 2 * from (select * from zhuisuo order by id asc) m order by m.id desc这句语句是不能执行的)
接下来我再举例关于top需要注意的细节
1、使用top返回随机行,很多人会想到用RAND函数从而得到这样一个语句
select top 4 id,name from zhuisuo order by rand();
经过多次查询后,你会失望的发现它没有返回随机行
这是因为每个查询只调用它一次而不是每行调用它一次
这时我们可以把RAND改为Newid
select top 4 id,name from zhuisuo order by newid();
这时就会得到你想要的结果了,在这里我们可以意识到NEWID具有更好的分布特性
2、注意insert中使用top
insert top (4) into zhuisuo
select * from zhuisuo order by id desc
很多网友会解释为把zhuisuo表中最后4条插入表
但执行完毕后又会让你失望了,插入的是最前面的4条
正确的倒叙插入top方法应该是
insert into zhuisuo
select top (4) * from zhuisuo order by id desc
这两条语句又有什么区别
其实第上面那条语句更本就没有排序(Top N Sort)