SQL,三种排名函数,用作排名使用
前言:
在某些应用场景中,我们经常会遇到一些排名的问题,比如按成绩或年龄排名。排名也有多种排名方式,如直接排名、分组排名,排名有间隔或排名无间隔等等,这篇文章将总结几种MySQL中常见的排名问题。
创建测试表
create table scores_tb (id int auto_increment primary key,xuehao int not null, score int not null
) ENGINE=InnoDB DEFAULT CHARSET=utf8;insert into scores_tb (xuehao,score) values (1001,89),(1002,99),(1003,96),(1004,96),(1005,92),(1006,90),(1007,90),(1008,94);# 查看下插入的数据
mysql> select * from scores_tb;
+----+--------+-------+
| id | xuehao | score |
+----+--------+-------+
| 1 | 1001 | 89 |
| 2 | 1002 | 99 |
| 3 | 1003 | 96 |
| 4 | 1004 | 96 |
| 5 | 1005 | 92 |
| 6 | 1006 | 90 |
| 7 | 1007 | 90 |
| 8 | 1008 | 94 |
+----+--------+-------+
1.普通排名
按分数高低直接排名,从1开始,往下排,类似于row number。下面我们给出查询语句及排名结果。
# 查询语句
SELECT xuehao, score, @curRank := @curRank + 1 AS rank
FROM scores_tb, (
SELECT @curRank := 0
) r
ORDER BY score desc;# 排序结果
+--------+-------+------+
| xuehao | score | rank |
+--------+-------+------+
| 1002 | 99 | 1 |
| 1003 | 96 | 2 |
| 1004 | 96 | 3 |
| 1008 | 94 | 4 |
| 1005 | 92 | 5 |
| 1006 | 90 | 6 |
| 1007 | 90 | 7 |
| 1001 | 89 | 8 |
+--------+-------+------+
上述查询语句中,我们申明了一个变量 @curRank ,并将此变量初始化为0,查得一行将此变量加一,并以此作为排名。我们看到这类排名是没间隔的并且有些分数相同但排名不同。
2.分数相同,名次相同,排名无间隔
# 查询语句
SELECT xuehao, score,
CASE
WHEN @prevRank = score THEN @curRank
WHEN @prevRank := score THEN @curRank := @curRank + 1
END AS rank
FROM scores_tb,
(SELECT @curRank :=0, @prevRank := NULL) r
ORDER BY score desc;# 排名结果
+--------+-------+------+
| xuehao | score | rank |
+--------+-------+------+
| 1002 | 99 | 1 |
| 1003 | 96 | 2 |
| 1004 | 96 | 2 |
| 1008 | 94 | 3 |
| 1005 | 92 | 4 |
| 1006 | 90 | 5 |
| 1007 | 90 | 5 |
| 1001 | 89 | 6 |
+--------+-------+------+
3.并列排名,排名有间隔
另外一种排名方式是相同的值排名相同,相同值的下一个名次应该是跳跃整数值,即排名有间隔。
# 查询语句
SELECT xuehao, score, rank FROM
(SELECT xuehao, score,
@curRank := IF(@prevRank = score, @curRank, @incRank) AS rank,
@incRank := @incRank + 1,
@prevRank := score
FROM scores_tb, (
SELECT @curRank :=0, @prevRank := NULL, @incRank := 1
) r
ORDER BY score desc) s;# 排名结果
+--------+-------+------+
| xuehao | score | rank |
+--------+-------+------+
| 1002 | 99 | 1 |
| 1003 | 96 | 2 |
| 1004 | 96 | 2 |
| 1008 | 94 | 4 |
| 1005 | 92 | 5 |
| 1006 | 90 | 6 |
| 1007 | 90 | 6 |
| 1001 | 89 | 8 |
+--------+-------+------+
上面介绍了三种排名方式,实现起来还是比较复杂的。好在MySQL8.0增加了窗口函数,使用内置函数可以轻松实现上述排名。
MySQL8.0 利用窗口函数实现排名
MySQL8.0中可以利用 ROW_NUMBER(),DENSE_RANK(),RANK() 三个窗口函数实现上述三种排名,需要注意的一点是as后的别名,千万不要与前面的函数名重名,否则会报错,下面给出这三种函数实现排名的案例:
# 三条语句对于上面三种排名
select xuehao,score, ROW_NUMBER() OVER(order by score desc) as row_r from scores_tb;
select xuehao,score, DENSE_RANK() OVER(order by score desc) as dense_r from scores_tb;
select xuehao,score, RANK() over(order by score desc) as r from scores_tb;# 一条语句也可以查询出不同排名
SELECT xuehao,score,ROW_NUMBER() OVER w AS 'row_r',DENSE_RANK() OVER w AS 'dense_r',RANK() OVER w AS 'r'
FROM `scores_tb`
WINDOW w AS (ORDER BY `score` desc);# 排名结果
+--------+-------+-------+---------+---+
| xuehao | score | row_r | dense_r | r |
+--------+-------+-------+---------+---+
| 1002 | 99 | 1 | 1 | 1 |
| 1003 | 96 | 2 | 2 | 2 |
| 1004 | 96 | 3 | 2 | 2 |
| 1008 | 94 | 4 | 3 | 4 |
| 1005 | 92 | 5 | 4 | 5 |
| 1006 | 90 | 6 | 5 | 6 |
| 1007 | 90 | 7 | 5 | 6 |
| 1001 | 89 | 8 | 6 | 8 |
+--------+-------+-------+---------+---+
总结:
本文给出三种不同场景下实现统计排名的SQL,可以根据不同业务需求选取合适的排名方案。对比MySQL8.0,发现利用窗口函数可以更轻松实现排名,其实业务需求远远比我们举的示例要复杂许多,用SQL实现此类业务需求还是需要慢慢积累的。
SQL,三种排名函数,用作排名使用相关推荐
- SQL 中 Rank、row_number、dense_rank 三种排序函数的区别
现有一张工资表,需要对其进行排名,工资相同的人并列排名,然后再排名,很多刚接触的小伙伴估计第一时间想到Rank()函数或row_number() 函数,但是结果出来后并不是自己想要的,在这里就给大家介 ...
- SQL中的三种count()函数
数据库的使用中,Count() 函数用于统计数据表的记录,返回匹配指定条件的行数. 三种Count() 函数 count(1).count(*).count(列名) 区别 1. count(1).co ...
- PL/SQL三种集合类型的比较
PL/SQL三种集合类型的比较<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" ...
- SQL三种连接:内连接、外连接、交叉连接
SQL三种连接:内连接.外连接.交叉连接 一.交叉连接(CROSS JOIN) 二.内连接(INNER JOIN) 三.外连接(LEFT JOIN.RIGHT JOIN.FULL JOIN) 1.左外 ...
- PostgreSQLl三种圆整函数对比
三种圆整函数: ceil(val):取val向上圆整的整数,不是是否大于.5,即1.2-->2, 1.8-->2,ceil有屋顶,天花板意思 floor(val): 取val向下圆整的整数 ...
- 三种开窗函数详细用法,图文详解
开窗函数的详细用法 一,开窗函数的语法 二,从聚合开窗函数sum(score) over(partition by name )讲起 三,开窗函数之first_value,last_value,lea ...
- Linq to Sql : 三种事务处理方式
Linq to SQL支持三种事务处理模型:显式本地事务.显式可分发事务.隐式事务.(from MSDN: 事务 (LINQ to SQL)).MSDN中描述得相对比较粗狂,下面就结合实例来对此进行 ...
- 三种sqrt函数实现
1:二分查找 思路:要实现一个sqrt函数,可以使用二分法,首先确定一个范围[begin, end],这个范围的中间数mid,看mid的平方是否等于x,如果相等,则返回mid,如果不等则缩小[begi ...
- java光标移动函数_文件内光标的移动 函数基础 定义函数的三种形式 函数的返回值 调用方式...
# with open(r'a.txt', 'r', encoding='utf-8')as f: # data1=f.read() # print('>1>:',data1) # pri ...
- MyBatis插入大量数据效率对比:foreach、SqlSession、sql三种方式批量插入
用mybatis插入数据执行效率对比,对比三种方式(测试数据库为MySQL), 使用 SqlSessionFactory,每一批数据执行一次提交 使用mybatis-plus框架的insert方法,f ...
最新文章
- 百度ERNIE 2.0发布!16项中英文任务表现超越BERT和XLNet
- 世界上有哪些代码量很少,但很牛逼很经典的算法或项目案例?
- 37 函数的定义和调用
- 公开SNS社区即时找朋友链的源代码和部署方案(续四)
- Mysql 死锁过程及案例详解之插入意向锁与自增锁备份锁日志锁Insert Intention Lock Auto-increment Lock Backup Lock Log Lock
- php静态变量的销毁
- 数据库、缓存、消息队列之外的下一站——Elasticsearch
- 绝大部分投资者没资格谈心态
- SQL SERVER 2008的top增强
- [Python] numpy库的简介和常用函数
- 9种常见的前端跨域解决方案(详解)
- vivo8.0系统机器最完美激活xposed框架的方法
- Android系统基础介绍
- HTML 语法教学之连结标签
- 计算机的u盘显示桌面,插入U盘后如何让U盘图标显示在Win7系统桌面上
- 安全狗入选信通院“业务安全推进计划”名单
- ZYThumbnailTableView类似于小型阅读器
- FPGA系列:ZCU102开发板上的第一个工程(MIG控制器)
- Beyond feelings的 introduction和 chapter1读后感
- android自学视频!2021年Android进阶者的新篇章,附面试题答案
热门文章
- 文件下载:POI读取word或Excel,修改内容后以流的形式输出到前端
- Excel公式——手机号区分运营商归属,电信,联通,移动手机号的区分
- 微信储存卡已拔出,如何解决
- Teamtoken:管理员工在企业的数字资产
- 中海达RTK(星移差分)使用指南
- java坐标代码_Java实现地理坐标判断
- 第二十二章:如何管理信息系统
- 在人工智能未来展望中,没有概念比“智能爆炸”更有冲击力
- iStat Menus 6.41 最好用颜值最高的Mac网速硬盘温度监控工具
- 初学用python写爬虫, 这里分享给大家一段爬取百度贴吧的代码(用面向对象的思想写的),请各位大佬们指点迷津