mysql rank函数_Sql 四大排名函数(ROW_NUMBER、RANK、DENSE_RANK、NTILE)简介

排名函数是Sql Server2005新增的功能,下面简单介绍一下他们各自的用法和区别。我们新建一张Order表并添加一些初始数据方便我们查看效果。

8904e255ea4ba3633d8d357a65c6c411.gif

表结构和初始数据Sql

附上表结构和初始数据图:

3a93015118262a7aedb0e066f5dbf921.png

一、ROW_NUMBER

row_number的用途的非常广泛,排序最好用他,一般可以用来实现web程序的分页,他会为查询出来的每一行记录生成一个序号,依次排序且不会重复,注意使用row_number函数时必须要用over子句选择对某一列进行排序才能生成序号。row_number用法实例:

select ROW_NUMBER() OVER(order by [SubTime] desc) as row_num,* from [Order]

查询结果如下图所示:

20894982ed83872fc157e5840332168d.png

图中的row_num列就是row_number函数生成的序号列,其基本原理是先使用over子句中的排序语句对记录进行排序,然后按照这个顺序生成序号。over子句中的order by子句与SQL语句中的order by子句没有任何关系,这两处的order by 可以完全不同,如以下sql,over子句中根据SubTime降序排列,Sql语句中则按TotalPrice降序排列。

select ROW_NUMBER() OVER(order by [SubTime] desc) as row_num,* from [Order] order by [TotalPrice] desc

查询结果如下图所示:

cdb507a56d8830669559aeea5df68592.png

利用row_number可以实现web程序的分页,我们来查询指定范围的表数据。例:根据订单提交时间倒序排列获取第三至第五条数据。

with orderSection as( select ROW_NUMBER() OVER(order by [SubTime] desc) rownum,* from [Order])select * from [orderSection] where rownum between 3 and 5 order by [SubTime] desc

查询结果如下图所示:

ed08987d5aacfca2f91b5f1e0cf5c3e1.png

注意:在使用row_number实现分页时需要特别注意一点,over子句中的order by 要与Sql排序记录中的order by 保持一致,否则得到的序号可能不是连续的。下面我们写一个例子来证实这一点,将上面Sql语句中的排序字段由SubTime改为TotalPrice。另外提一下,对于带有子查询和CTE的查询,子查询和CTE查询有序并不代表整个查询有序,除非显示指定了order by。

with orderSection as( select ROW_NUMBER() OVER(order by [SubTime] desc) rownum,* from [Order])select * from [orderSection] where rownum between 3 and 5 order by [TotalPrice] desc

查询结果如下图所示:

6ece3c88c5a53929c0e8b9a32fbc468b.png

二、RANK

rank函数用于返回结果集的分区内每行的排名, 行的排名是相关行之前的排名数加一。简单来说rank函数就是对查询出来的记录进行排名,与row_number函数不同的是,rank函数考虑到了over子句中排序字段值相同的情况,如果使用rank函数来生成序号,over子句中排序字段值相同的序号是一样的,后面字段值不相同的序号将跳过相同的排名号排下一个,也就是相关行之前的排名数加一,可以理解为根据当前的记录数生成序号,后面的记录依此类推。可能我描述的比较苍白,理解起来也比较吃力,我们直接上代码,rank函数的使用方法与row_number函数完全相同。

select RANK() OVER(order by [UserId]) as rank,* from [Order]

查询结果如下图所示:

b460e1f91ba1591149b9a05f69532c60.png

由上图可以看出,rank函数在进行排名时,同一组的序号是一样的,而后面的则是根据当前的记录数依次类推,图中第一、二条记录的用户Id相同,所以他们的序号是一样的,第三条记录的序号则是3。

三、DENSE_RANK

dense_rank函数的功能与rank函数类似,dense_rank函数在生成序号时是连续的,而rank函数生成的序号有可能不连续。dense_rank函数出现相同排名时,将不跳过相同排名号,rank值紧接上一次的rank值。在各个分组内,rank()是跳跃排序,有两个第一名时接下来就是第四名,dense_rank()是连续排序,有两个第一名时仍然跟着第二名。将上面的Sql语句改由dense_rank函数来实现。

select DENSE_RANK() OVER(order by [UserId]) as den_rank,* from [Order]

查询结果如下图所示:

83d0fe3b145f726a89e37e4486328e8a.png

图中第一、二条记录的用户Id相同,所以他们的序号是一样的,第三条记录的序号紧接上一个的序号,所以为2不为3,后面的依此类推。

四、NTILE

ntile函数可以对序号进行分组处理,将有序分区中的行分发到指定数目的组中。 各个组有编号,编号从一开始。 对于每一个行,ntile 将返回此行所属的组的编号。这就相当于将查询出来的记录集放到指定长度的数组中,每一个数组元素存放一定数量的记录。ntile函数为每条记录生成的序号就是这条记录所有的数组元素的索引(从1开始)。也可以将每一个分配记录的数组元素称为“桶”。ntile函数有一个参数,用来指定桶数。下面的SQL语句使用ntile函数对Order表进行了装桶处理:

select NTILE(4) OVER(order by [SubTime] desc) as ntile,* from [Order]

查询结果如下图所示:

8263bd1a6ce62e48fbb2cddb8f36f4d3.png

Order表的总记录数是6条,而上面的Sql语句ntile函数指定的组数是4,那么Sql Server2005是怎么来决定每一组应该分多少条记录呢?这里我们就需要了解ntile函数的分组依据(约定)。

ntile函数的分组依据(约定):

1、每组的记录数不能大于它上一组的记录数,即编号小的桶放的记录数不能小于编号大的桶。也就是说,第1组中的记录数只能大于等于第2组及以后各组中的记录数。

2、所有组中的记录数要么都相同,要么从某一个记录较少的组(命名为X)开始后面所有组的记录数都与该组(X组)的记录数相同。也就是说,如果有个组,前三组的记录数都是9,而第四组的记录数是8,那么第五组和第六组的记录数也必须是8。

这里对约定2进行详细说明一下,以便于更好的理解。

首先系统会去检查能不能对所有满足条件的记录进行平均分组,若能则直接平均分配就完成分组了;若不能,则会先分出一个组,这个组分多少条记录呢?就是 (总记录数/总组数)+1 条,之所以分配 (总记录数/总组数)+1 条是因为当不能进行平均分组时,总记录数%总组数肯定是有余的,又因为分组约定1,所以先分出去的组需要+1条。

分完之后系统会继续去比较余下的记录数和未分配的组数能不能进行平均分配,若能,则平均分配余下的记录;若不能,则再分出去一组,这个组的记录数也是(总记录数/总组数)+1条。

然后系统继续去比较余下的记录数和未分配的组数能不能进行平均分配,若能,则平均分配余下的记录;若还是不能,则再分配出去一组,继续比较余下的......这样一直进行下去,直至分组完成。

举个例子,将51条记录分配成5组,51%5==1不能平均分配,则先分出去一组(51/5)+1=11条记录,然后比较余下的 51-11=40 条记录能否平均分配给未分配的4组,能平均分配,则剩下的4组,每组各40/4=10 条记录,分配完成,分配结果为:11,10,10,10,10,晓菜鸟我开始就错误的以为他会分配成 11,11,11,11,7。

根据上面的两个约定,可以得出如下的算法:

8ec9e750a95daba013a93937c41bc6fe.gif//mod表示取余,p表示取整.if(记录总数 mod 桶数==0)

{

recordCount=记录总数 p 桶数;

//将每桶的记录数都设为recordCount.}else{

recordCount1=记录总数 p 桶数+1;

int n=1;//n表示桶中记录数为recordCount1的最大桶数.  m=recordCount1*n;  while(((记录总数-m) mod (桶数- n)) !=0)

{

n++;

m=recordCount1*n;

}

recordCount2=(记录总数-m) p (桶数-n);

//将前n个桶的记录数设为recordCount1.  //将n+1个至后面所有桶的记录数设为recordCount2.}

8ec9e750a95daba013a93937c41bc6fe.gif

8904e255ea4ba3633d8d357a65c6c411.gif NTILE()函数算法实现代码

根据上面的算法,如果总记录数为59,总组数为5,则 n=4 , recordCount1=12 , recordCount2=11,分组结果为 :12,12,12,12,11。

如果总记录数为53,总组数为5,则 n=3 , recordCount1=11 , recordCount2=10,分组结果为:11,11,11,10,10。

就拿上面的例子来说,总记录数为6,总组数为4,通过算法得到 n=2 , recordCount1=2 , recordCount2=1,分组结果为:2,2,1,1。

select ntile,COUNT([ID]) recordCount from ( select NTILE(4) OVER(order by [SubTime] desc) as ntile,* from [Order]) as tgroup by t.ntile

运行Sql,分组结果如图:

3ac84774022dd97dd1f50f51ec1bf196.png

比对算法与Sql Server的分组结果是一致的,说明算法没错。:)

总结:

在使用排名函数的时候需要注意以下三点:

1、排名函数必须有 OVER 子句。

2、排名函数必须有包含 ORDER BY 的 OVER 子句。

3、分组内从1开始排序。

本文讲解了Sql 四大排名函数(ROW_NUMBER、RANK、DENSE_RANK、NTILE)相关知识,更多相关内容请关注php中文网。

相关推荐:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/246019.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git2.29.2.2怎么安装_MySQL5.5怎么安装

安装MySQL5.5的步骤:1、 官网下载mysql5.5下载地址:http://dev.mysql.com/downloads/mysql/5.5.html#downloads2、 安装mysql5.5注意,安装之前,请关闭杀毒软件。1)、 打开下载的mysql-5.5.53-winx64.msi2) 、点击下一步3)、 选中复…

未声明spire。它可能因保护级别而不可访问_信息系统安全:访问控制技术概述...

1.访问控制基本概念身份认证技术解决了识别“用户是谁”的问题,那么认证通过的用户是不是可以无条件地使用所有资源呢?答案是否定的。访问控制(Access Control)技术就是用来管理用户对系统资源的访问。访问控制是国际标准ISO7498-2中的五项安全服务之一&…

c++反汇编与逆向分析技术揭秘_C++反汇编与逆向分析技术揭秘

一、单类继承在父类中声明为私有的成员,子类对象无法直接访问,但是在子类对象的内存结构中,父类私有的成员数据依然存在。C语法规定的访问限制仅限于编译层面,在编译过程中进行语法检查,因此访问控制不会影响对象的内存…

std::atomic原子操作

第十一节std::atomic原子操作_HITXJ的博客-CSDN博客_std::atomic用法

php与mysql列表_PHP+Mysql+jQuery实现的查询和列表框选择

本篇文章主要介绍PHPMysqljQuery实现的查询和列表框选择,感兴趣的朋友参考下,希望对大家有所帮助。本文讲解如何通过ajax查询mysql数据,并将返回的数据显示在待选列表中,再通过选择最终将选项加入到已选区,可以用在许多…

range函数python2和3区别_range函数python2和3区别

range函数是一个用来创建算数级数序列的通用函数,返回一个[start, start step, start 2 * step, ...]结构的整数序列;py2中的range()函数用法:(推荐学习:Python视频教程) range()返回的是一个列表>>&…

Unity SRP自定义渲染管线 -- 2.Custom Shaders

本章将接着上一篇文章,在初步实现一个渲染管线后来创建自定义的shader。上一篇文章的链接 https://blog.csdn.net/yinfourever/article/details/90516602。在本章中,将完成以下内容: 写一个HLSL Shader定义constant buffer(常量缓…

tcp 三次握手与四次挥手_TCP三次握手与四次挥手详解

TCP报文结构源端口和目的端口:各占2个字节,分别写入源端口号和目的端口号。序号:占4个字节。序号使用mod运算。TCP是面向字节流的,在一个TCP连接中传送的字节流中的每一个字节都按顺序编号。故该字段也叫做“报文段序号”。确认序…

网关和路由器的区别_5G工业路由器与5G DTU的区别介绍详解

5G工业路由器和5G DTU都是实现无线网络数据传输功能,而两者间的区别主要从使用方法、外观接口以及应用环境等方面区分,今天给大家介绍5G工业路由器和5G DTU的一些不同点。使用方法的不同:5G工业路由器:5G路由器可对以太网、现场总线通信协议进…

7628刷breed_自制各类路由原厂直刷Breed的文件,无需修改mac无需重刷无线

本帖最后由 showme99 于 2017-3-25 16:35 编辑在原厂页面直接选择相应的刷机文件刷机,文件很小256K,大约十秒左右就自动进入Breed后直接刷入dd-wrt,opentwrt,gargoyle等固件即可。无需在Breed里设置MAC地址,也无需刷入ART无线文件&#xff0c…

c语言获取系统剩余内存_C语言编程中的“堆”和“栈”七大不同之处

更多精彩,请点击上方蓝字关注我们!对于编程初学者来说会接触到一些难以理解的名称,比如堆(heap)、栈(stack)、堆栈(stack)等。初学开发过程中往往让人混淆不清。今天我们来谈谈堆和栈的具体区别,来帮助初学者理清思路。堆和栈的区…

sql between包括两端吗_SQL大全

作者:静默虚空排版:MarkerHub原文:https://juejin.im/post/5c7e524af265da2d914db18f本文针对关系型数据库的一般语法。限于篇幅,本文侧重说明用法,不会展开讲解特性、原理。一、基本概念数据库术语数据库(database) -…

python交互模式什么意思_Python中的交互模式是什么

让开发者能快速学习、测试 Python 的各种功能,Python 提供的“python”命令不仅能用于运行 Python 程序,也可作为一个交互式解释器一一开发者逐行输入 Python 代码,它逐行解释执行。 当输入“python”命令时,可以看到如下输出结果…

idea创建springboot项目+mybatis_Spring Boot + MyBatis 多模块项目搭建教程

Java后端,选择“”优质文章,及时送达作者 | 枫本非凡链接 | cnblogs.com/orzlin/p/9717399.html上篇 | IDEA 远程一键部署 Spring Boot 到 Docker一、前言最近公司项目准备开始重构,框架选定为SpringBootMybatis,本篇主要记录了在…

下载nodejs的mysql安装包下载安装_Node.js安装 下载

1、安装Node.jshttps://nodejs.org/en/安装步骤:点击安装包按提示进行安装Node.js 安装配置本章节我们将向大家介绍在 Windows 和 Linux 上安装 Node.js 的方法。本安装教程以 Node.js v4.4.3 LTS(长期支持版本)版本为例。你可以根据不同平台系统选择你需要的 Node.…

redistemplate注入为null_Windows DLL 注入技术

Windows DLL 注入技术 本文主要介绍四种常见的 Windows DLL 注入技术。分别为全局钩子、远线程钩子、突破 SESSION 0 隔离的远线程注入和 APC 注入。全局钩子注入Windows 中大部分应用是基于 Windows 的消息机制,Windows提供截获这些消息的钩子函数。根据钩子作用的…

nginx location 正则表达式匹配多个地址_就是要让你搞懂Nginx,这篇就够了!

Nginx 是一个高性能的 HTTP 和反向代理服务器,特点是占用内存少,并发能力强,事实上 Nginx 的并发能力确实在同类型的网页服务器中表现较好。Nginx 专为性能优化而开发,性能是其最重要的要求,十分注重效率,有…

mysql查询网址_bootstrap+flask+mysql实现网站查询

之前那篇文章是flaskredis的,如果用flaskmysql怎么实现呢?创建数据库:CREATE DATABASE web12306 DEFAULT CHARACTER SET utf8;创建表:CREATE TABLE web12306 (user_email varchar(100) NOT NULL DEFAULT ,user_pass varchar(100)…

dubbo官方文档_不可忽视的Dubbo线程池

问题描述线上突然出现Dubbo超时调用,时间刚好为Consumer端设置的超时时间。有好几个不同的接口都报超时了第1次调用超时,第2次(或第3次)重试调用非常快(正常水平)Dubbo调用超时的情况集中出现了3次&#xf…

python中比较重要的几个函数_Python 几个重要的内置函数 python中的内置函数和关键字需要背过吗...

python重要的几个内置函数用法python内置函数什么用忘不掉的是回忆,继续的是生活,错过的,就当是路过吧。来来往往身边出现很多人,总有一个位置,一直没有变。看看温暖的阳光,偶尔还是会想一想。Python内置函…