select top x with ties和select语句执行顺序

创建一个student表:
create table student(name nvarchar(10) primary key,
                     score int);
go
insert student values('aa',10),
                     ('bb',20),
                     ('cc',30),
                     ('dd',40),
                     ('ee',50),
                     ('ff',60),
                     ('gg',70),
                     ('hh',80),
                     ('ii',90),
                     ('jj',100),
                     ('kk',100),
                     ('ll',90),
                     ('mm',95);
取成绩第一名,使用语句
select top 1 name,score from student order by score desc;
image

只有一条,可有两个都是100分的呀。

select top 2 name,score from student order by score desc;

image

可以加上with ties

select top 1 with ties name,score from student order by score desc;

image

继续看with ties,我取前两名呢?

image

擦,和取第一名是一样的呀!这不是我要的结果呀,两个100的应该是并列第一名,第二名应该是再往下排呀!

我们继续用with ties,

select top 3 with ties name,score from student order by score desc;

image

select top 4 with ties name,score from student order by score desc;

image

经过上面的几个select top x with ties可以看出,他只是根据”top x”中的第x个值去判断是否有重复的,如果第X个值没有重复的,结果和top x无with ties是一样的;当然如果第x个值有重复的,但已经在前一个值显示了,那他的结果和top  x无with ties也是一样的,比如上文中的取前两名,select top 2 with ties name , score from student order by score desc.

top 3 和top 3 with ties结果是一样的。

select top 3 name,score from student order by score desc;

image

那如果我想让排名的结果是:两个100分的都是第一名,第二名95分,第三名也是两个都是90分

那就要用到窗口函数(也叫开窗函数)

下面这个排名按分数由高向低的排序

select name,score from student order by score desc;

image

窗口函数也可以的

select row_number() over (order by score desc) as 排名,
          name,
         score
from student;

image

再看看下面这个语句呢

select dense_rank() over (order by score desc) as 排名,
          name,
          score
from student;

image

13个人,排名只有11,两个第一,两个第三,这是否就是你想要的呢?

还有个语句,虽然第一是两个人,但是否要把第二名给占掉呢,毕竟是两个人啊

select rank() over (order by score desc) as 排名,
          name,
          score
from student;

image

第二名和第五名没了,因为第一名是两个,把第二名的名额给占了;第四名又是两个,又把第五名的名额给占了。

关于第一个top x with ties的问题,涉及到select语句执行顺序的问题,如果order by是后于select语句执行,那结果还成立吗?个人认为不成立,我一直认为order by是select语句中最后执行的。在网上查询的结果不是很好,有的是select在前执行,有的是order by在前执行。

下面是微软网站上的说明,应该还是select在order by之前,但是top在order by之后,这样就可以理解了。

http://msdn.microsoft.com/zh-cn/library/ms189499.aspx 

SELECT 语句的逻辑处理顺序

以下步骤显示 SELECT 语句的逻辑处理顺序(即绑定顺序)。 此顺序确定在一个步骤中定义的对象何时可用于后续步骤中的子句。 例如,如果查询处理器可以绑定到(访问)在 FROM 子句中定义的表或视图,则这些对象及其列可用于所有后续步骤。 相反,因为 SELECT 子句处于步骤 8,所以,在该子句中定义的任何列别名或派生列都无法被之前的子句引用。 不过,它们可由 ORDER BY 子句之类的后续子句引用。 请注意,该语句的实际物理执行由查询处理器确定,因此顺序可能与此列表不同。

  1. ON

  2. JOIN

  3. WHERE

  4. GROUP BY

  5. WITH CUBE 或 WITH ROLLUP

  6. HAVING

  7. SELECT

  8. DISTINCT

  9. ORDER BY

  10. TOP

另附一图,在网上找的,供参考,来源:http://www.jb51.net/article/32066.htm

image

where子句为什么不能包含聚合函数,因为求解聚合函数是在where子句之后执行的。

原文地址:https://www.cnblogs.com/cnmarkao/p/3754599.html