提到排名函数我们首先可能想到的是order by,这个是排序,不是排名,排名需要在前面加个名次序号的,order by是没有这个功能的。还可能会想到identity(1,1),它也给了一个序号,但是不能保证给出的序号是连续升序的。除非能够保证所有的Insert语句都能够正确成功地完成,并且没有删除操作,实际的使用中大多数的表都不能保证这样。

好在SQL Server中提供了一些排名函数来辅助实现这些功能。排名函数按照需要的顺序对数据进行排名,并提供一个值对数据。下面来了解一下这些排序函数功能。

  

ROW_NUMBER

 

ROW_NUMBER函数允许以上升,连续的顺序给每一行数据一个序号,注意ROW_NUMBER()后面一定要跟着over子句。来看语句:

1use AdventureWorks
2select
3ROW_NUMBER() over(order by LastName) as RowNum,
4FirstName+' '+ LastName as FullName
5from HumanResources.vEmployee
6where JobTitle='Production Technician - WC60'

这个语句对符合条件(JobTitle='Production Technician - WC60')的LastName按照升序排列,并加上排序的序号,这个序号是连续上升的。结果如下图1是部分结果。

图1

我们可以看到第一个人的LastName是Abercrombie,第二个人的LastName是Adams,以次类推。

  

PARTITION

 

如果我们想再细分一下,在一个小的分组范围内排序该怎么办呢?就是说让LastName以‘A’开头的作为第一组,在这个组内进行排序。以‘B’开头的作为第二组,在这个组内排序。以‘C’开头的作为第三组,在这个组内进行排序,如此等等。这里有一个很简单的实际例子,假如上面这些人都来参加同一场马拉松比赛,其中有男子组,女子组,男子残疾组,女子残疾组,60岁以上组等等。不管参赛者以第几位触线,名次都以他们的小组为基准。

可以通过PARTITION BY选项来重新排序,给数据分区或者数据区域唯一的递增序号。来看下面的语句:

[注] partition n. 划分,分开;[数] 分割;隔墙;隔离物;vt. [数] 分割;分隔;区分

1select
2ROW_NUMBER() over(PARTITION by substring(LastName,1,1) order by LastName) as RowNum,
3FirstName+' '+ LastName as FullName
4from HumanResources.vEmployee
5where JobTitle='Production Technician - WC60'

这里模拟上面的情况,首先以Last Name的第一个字母作为分组,然后以第二个字母以后的字母来分组排序。来看看结果,如图2



图2

假设LastName以‘A’开头的是男子组,这个组有共有三个人,Kim Abercrombie是冠军,Jay Adams是亚军,Nancy Anderson是季军。假设LastName以‘B’开头的是女子组,这个组只有一个人Bryan Baker,无论如何她都是冠军。等等如此类推。这样一眼就能看出他们的小组名次了。

这里你可能会觉得使用order by一样可以得到这样类似的结果。如下代码:

1 select
2 FirstName+' '+ LastName as FullName
3 from HumanResources.vEmployee
4 where JobTitle='Production Technician - WC60'
5 order by substring(LastName,1,1) ,LastName

这个把order by放在最后,排序放在最后,首先按照LastName的首字母排序,再按照剩整个LastName排序,结果如下图3



图3

结果和上面大致相同,可是少了前面的名次序号。于是我又对她进行了修改,代码如下:

1select
2ROW_NUMBER() over(order by substring(LastName,1,1),LastName) as RowNum,
3FirstName+' '+ LastName as FullName
4from HumanResources.vEmployee
5where JobTitle='Production Technician - WC60'
这个和上面的类似,在排名函数中使用order by,并且是按照多个字段排序。来看看结果如图4



图4

排序没有错误,是我们想要的分组排序,但是前面的名次没有分组区分,和图1没有什么差别。可见图3和图4的做法完全是多余,纯属臆造,其实只要order by LastName都能得到正确的排序,只有partition by才是正解。通过上面的例子也可以对排序,排名这二者之间的区别有一个认识,他们虽然有相似之处,但是排名始终会产生一个名次序号,排序只要得到正确的顺序就好。

    

RANK

 

还是拿马拉松比赛来说事,如果有同时撞线的情况发生应该怎么计名次呢?例如A第一个撞线,B和C同时第二个撞线,D第三个撞线,如果我们想把D的名次计为第4名应该怎么处理呢?就是说不计顺序名次,只计人数。这时就可以使用RANK函数了。

[注] rank n. 等级;队列;排;军衔vt. 排列;把…分等vi. 列队;列为

在order by子句中定义的列上,如果返回一行数据与另一行具有相同的值,rank函数将给这些行赋予相同的排名数值。在排名的过程中,保持一个内部计数值,当值有所改变时,排名序号将有一个跳跃。

来看下面的语句:

1select
2ROW_NUMBER() over(order by Department) as RowNum,
3RANK() over(order by Department) as Ranking,
4FirstName+' '+ LastName as FullName,
5Department
6from HumanResources.vEmployeeDepartment
7order by RowNum

rank()函数右面也要跟上一个over子句。为了看到效果我们以Department作为排序字段,可以看到RowNum作为升序连续排名,Ranking作为计同排名,当Department的值相同时,Ranking中的值保持不变,当Ranking中的值发生变化时,Ranking列中的值将跳跃到正确的排名数值。来看结果:



图5

从这个结果中我们可以说这次马拉松赛跑的排名是:Tengiz Kharatishvili,Zainal Arifin,Sean Chai,Karen Berge,Chris Norred并列第1,Michael Sullivan,Sharon Salavaria,Roberto Tamburello,Gail Erickson,Jossef Goldberg并列第6,如此等等。



DENSE_RANK

在上面的例子中,A第一个撞线,B和C同时第二个撞线,D第三个撞线,如果我们想把B和C的名次计位第2名,D的名次计为第3名应该怎么处理呢?就是说考虑并列名次。这里使用DENSE_RANK函数,来看下面的代码。

1select
2ROW_NUMBER() over(order by Department) as RowNum,
3DENSE_RANK() over(order by Department) as Ranking,
4FirstName+' '+ LastName as FullName,
5Department
6from HumanResources.vEmployeeDepartment
7order by RowNum

结果如下:



图6

按照这个结果,我们可以说这次马拉松赛跑的排名是:Tengiz Kharatishvili,Zainal Arifin,Sean Chai,Karen Berge,Chris Norred并列第1,Michael Sullivan,Sharon Salavaria,Roberto Tamburello,Gail Erickson,Jossef Goldberg,Terri Duffy并列第2,等等如此。

NTILE

在开始这个之前,先来一段小插曲。梭罗是铅笔的发明者,不过他没有申请专利。据说他天赋异禀,在父亲的铅笔厂里面打包铅笔的时候,从一堆铅笔里面抓取一把,每次都能精确地抓到一打12支。他在森林中目测两颗树之间的距离,和护林员用卷尺测量的结果相差无几。现在如果我们想从一张表中抓取多比数据,每一笔都是相同的数目,并且标明第几组该怎么办呢?NTILE函数提供了这个功能,他能。来看代码:

1 select
2 NTILE(30) over(order by Department) as NTiles,
3 FirstName+' '+ LastName as FullName,
4 Department
5 from HumanResources.vEmployeeDepartment

现在我们要抓取30个组的数据,并保证尽可能的保证每组数目相同。结果如下,



图7

这个视图中共290条数据,290/30=9.7约等于10,所以每组10条数据,如图每一条数据都有一个组号。这个结果要比索罗精确。

SQL点滴20—T-SQL中的排名函数相关推荐

  1. sql游标 while_用SQL Server中的排名函数替换SQL While循环和游标,以提高查询性能

    sql游标 while SQL While loop and cursor are the most common approach to repeat a statement on conditio ...

  2. java中rank函数_SQL中的排名函数(ROW_NUMBER、RANK、DENSE_RANK、NTILE)简介

    排名函数是Sql Server2005新增的功能,下面简单介绍一下他们各自的用法和区别. 在使用排名函数的时候需要注意以下三点: 1.排名函数必须有 OVER 子句. 2.排名函数必须有包含 ORDE ...

  3. mysql中的排名函数rank()、dense_rank()、row_number()

    排名函数rank().dense_rank().row_number()的比较 1.问题描述 在写LeetCode178. 分数排名时,它的要求是输出"无间隔"的分数排名,于是本文 ...

  4. 聚合函数的计算机控件,sql – 当我们在联接中使用聚合函数时如何使用Group By子句?...

    我想加入三个表并计算表A的总和(数量). 我试了一下,得到了想要的输出.但我仍然混淆基于聚合函数和Group By子句. 在通过连接两个或多个表来计算总和值时,我们需要在Group By子句中提及哪些 ...

  5. sql server怎么实现mysql 中的locate函数

    LOCATE()是判断字符串中是否包含字符串的函数 MySQL中LOCATE()函数直接用在sqlServer是不行的,需要替换成CHARINDEX 例如: select * from sys_dep ...

  6. oracle的排名函数,oracle中的排名函数

    rank,dense_rank,row_number,以及分组排名partition rank:排名会出现并列第n名,它之后的会跳过空出的名次,例如:1,2,2,4 dense_rank:排名会出现并 ...

  7. sql 除以_不可思议的SQL排名函数,被您无视了么?

    经常写SQL脚本的朋友,对查询的多样化要求可能会经常头疼.数据库SQL的语法是固定的.但应用要求却是千差万别的.依靠我们所掌握的知识,大部分的查询需求我们还是有办法的解决的,但总有那么一些要求,把我们 ...

  8. 在MySQL中实现Rank高级排名函数

    在MySQL中实现Rank高级排名函数 前言 用例表 1.在MySQL中实现普通排名 2.在MySQL中实现并列连续序号排名 3.在MySQL中实现并列非连续序号排名 4.随机获得一条数据 5.判断数 ...

  9. 【Python】Pandas中的宝藏函数-rank()

    所谓的排名,就是一组数据,我们想要知道每一条数据在整体中的名次,需要的是输出名次,并不改变原数据结构. 排序会改变原来的数据结构,且不会返回名次,这一点区别需要弄明白.初学的时候容易弄混淆. 本文将通 ...

最新文章

  1. 独白:我为什么要从BTC转向支持BCH?
  2. nginx进程管理之worker进程
  3. VTK修炼之道44:图形进阶_vtkPolyData数据源讨论与数据创建
  4. ABAddressBookSave关于保存到通讯录失败的问题
  5. java天气预报webservice_webservice之实现天气预报
  6. python入门需要有什么基础?
  7. 前端开发常用免费资源,显著提升工作效率
  8. 混合汇编 src-control
  9. im即时通讯开发:群聊消息的已读未读功能
  10. 乔治城大学 计算机排名,乔治城大学计算机科学硕士排名第40(2020年TFE Times排名)...
  11. aardio - 制作启动等待动画窗口
  12. Jetson Xavier NX——重新刷系统
  13. 【转载】客单价是什么意思?如何提高客单价?
  14. EasyCVR使用大华SDK接入时录像显示失败是什么原因?该如何解决?
  15. Dbus启动问题 Failed to get D-Bus connection: Operation not permitted
  16. Maven报错Original error: Could not transfer artifact
  17. 2022-2028全球自动超声波仪器清洗器行业调研及趋势分析报告
  18. 计算机专业英语简介模板,计算机专业英文简历模版
  19. 视频伪原创批量处理工具 md5视频 修改器
  20. 7-6 最短工期 (25 分)(C++版)

热门文章

  1. 原创:centos7.1下 ZooKeeper 集群安装配置+Python实战范例
  2. ylbtech-LanguageSamples-SimpleVariance
  3. 基于visual Studio2013解决C语言竞赛题之1081shell排序
  4. 张一鸣演讲全文:外部波澜起伏,内心平静如常
  5. PMCAFF微课堂已结束 | 前YY产品总监深度揭秘P2P运营推广精髓
  6. 一位互联网老兵分享,社会化运营案例解析(宜信内部干货)
  7. 【干货】七步,让你的网页表单更亲切
  8. 刷题中,效率好低,哈哈哈 -----1.Two Sum
  9. C++ STL vector(向量)
  10. 订单分类和评分--vue.js学习笔记2