MySQL窗口函数实现榜单排名

目录
  • rank()
  • dense_rank()
  • row_number()
  • rank()函数的模拟实现
  • dense_rank()的模拟实现
  • row_number的模拟实现
  • 总结

相信大家在日常的开发中经常会碰到榜单类的活动需求,通常在榜单中都会要求返回排名,今天我们就用MySQL的窗口函数来快速实现一下

首先,先建一个测试表

create table praise_record(
    id bigint primary key auto_increment,
    name varchar(10),
    praise_num int
) ENGINE=InnoDB;

然后让chatGpt给我们生成几条测试数据

INSERT INTO praise_record (name, praise_num) VALUES ('John', 5);
INSERT INTO praise_record (name, praise_num) VALUES ('Jane', 3);
INSERT INTO praise_record (name, praise_num) VALUES ('Bob', 10);
INSERT INTO praise_record (name, praise_num) VALUES ('Alice', 3);
INSERT INTO praise_record (name, praise_num) VALUES ('David', 7);
INSERT INTO praise_record (name, praise_num) VALUES ('oct', 7);

然后就可以开始实现我们的需求:返回点赞的榜单,并返回排名

rank()

使用rank()函数返回点赞的榜单, rank() over()

## 注意这里返回的rank字段要用反引号包起来
select name, praise_num, rank() over (order by praise_num desc) as `rank` from praise_record;
+-------+------------+------+
| name  | praise_num | rank |
+-------+------------+------+
| Bob   |         10 |    1 |
| David |          7 |    2 |
| oct   |          7 |    2 |
| John  |          5 |    4 |
| Jane  |          3 |    5 |
| Alice |          3 |    5 |
+-------+------------+------+

可以看到使用rank()函数的时候相同的点赞数会返回相同的排名,排名会产生跳跃,最终的排名不是连续的

dense_rank()

使用dense_rank()函数返回点赞的榜单, dense_rank() over()

 select name, praise_num, dense_rank() over (order by praise_num desc) as `rank` from praise_record;

 +-------+------------+------+
| name  | praise_num | rank |
+-------+------------+------+
| Bob   |         10 |    1 |
| David |          7 |    2 |
| oct   |          7 |    2 |
| John  |          5 |    3 |
| Jane  |          3 |    4 |
| Alice |          3 |    4 |
+-------+------------+------+

与rank()函数相同的是,相同点赞数会返回相同的排名,但是dense_rank()返回的最终排名是连续的排名

row_number()

row_number()函数返回点赞的榜单,row_number() over()

 select name, praise_num, row_number() over (order by praise_num desc) as `rank` from praise_record;
 +-------+------------+------+
| name  | praise_num | rank |
+-------+------------+------+
| Bob   |         10 |    1 |
| David |          7 |    2 |
| oct   |          7 |    3 |
| John  |          5 |    4 |
| Jane  |          3 |    5 |
| Alice |          3 |    6 |
+-------+------------+------+

row_number()函数适合当返回的列表只需要序号时使用

以上三个函数都是MySQL8.0新加入的,所以在MySQL5.7这些老版本上我们可以模拟实现一下,顺便学习一下这三个窗口函数的实现原理

rank()函数的模拟实现

select p1.name, p1.praise_num, count(p2.praise_num) + 1 as `rank` from praise_record p1
left join praise_record p2 on p1.praise_num < p2.praise_num
group by p1.name, p1.praise_num
order by `rank`;
+-------+------------+------+
| name  | praise_num | rank |
+-------+------------+------+
| Bob   |         10 |    1 |
| David |          7 |    2 |
| oct   |          7 |    2 |
| John  |          5 |    4 |
| Jane  |          3 |    5 |
| Alice |          3 |    5 |
+-------+------------+------+

我们可以使用自联接的方式将每个分数低于当前行分数的记录计数,最后将计数值加1作为当前行的排名,来模拟实现rank()

dense_rank()的模拟实现

select p1.name, p1.praise_num, count(distinct p2.praise_num) + 1 as `dense_rank` from praise_record p1
left join praise_record p2 on p1.praise_num < p2.praise_num
group by p1.name, p1.praise_num
order by `dense_rank`;
+-------+------------+------------+
| name  | praise_num | dense_rank |
+-------+------------+------------+
| Bob   |         10 |          1 |
| oct   |          7 |          2 |
| David |          7 |          2 |
| John  |          5 |          3 |
| Jane  |          3 |          4 |
| Alice |          3 |          4 |
+-------+------------+------------+

dense_rank的实现与rank差不多,唯一的区别是增加了distinct对点赞数做了去重,这样子对不同的点赞数返回的排名就是连续的

row_number的模拟实现

##使用自定义变量得先初始化
set @rowNum = 0;
select name, praise_num, @rowNum := @rowNum +1 as `row_number`  from praise_record order by praise_num desc ;
+-------+------------+------------+
| name  | praise_num | row_number |
+-------+------------+------------+
| Bob   |         10 |          1 |
| David |          7 |          2 |
| oct   |          7 |          3 |
| John  |          5 |          4 |
| Jane  |          3 |          5 |
| Alice |          3 |          6 |
+-------+------------+------------+

我们可以使用一个rowNum变量来记录行号,每一行的数据rowNUm都+1,这样子就可以得到我们想要的序号

总结

1.rank()函数返回的排名会产生跳跃

2.dense_rank()函数返回的排名是连续的

3.row_number()函数返回的排名类似序号

4.窗口函数是MySQL8.0新增的特性,如果在低版本的MySQL要自己模拟实现一下

到此这篇关于MySQL窗口函数实现榜单排名的文章就介绍到这了,更多相关MySQL 榜单排名内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 总结几种MySQL中常见的排名问题

    前言: 在某些应用场景中,我们经常会遇到一些排名的问题,比如按成绩或年龄排名.排名也有多种排名方式,如直接排名.分组排名,排名有间隔或排名无间隔等等,这篇文章将总结几种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

  • Mysql教程分组排名实现示例详解

    目录 1.数据源 2.数据整体排名 1)普通排名 2)并列排名 3)并列排名 3.数据分组后组内排名 1)分组普通排名 2)分组后并列排名 3)分组后并列排名 4.分组后取各组的前两名 1.数据源 2.数据整体排名 1)普通排名 从1开始,按照顺序一次往下排(相同的值也是不同的排名). set @rank =0; select city , score, @rank := @rank+1 rank from cs order by score desc; 结果如下: 2)并列排名 相同的值是相同

  • MySQL中给自定义的字段查询结果添加排名的方法

    我正在用 MySQL 客户端的时候,突然想到如果可以给查询结果添加排名该多好啊,然后就找到了一个简单的解决办法. 下面是一个示例表的数据:  然后我们要根据 Roll_No 字段进行排序并给出排名,我们首先必须定义一个初始值为0的变量,然后在查询结果中使用这个变量. 如下面的代码: SET @counter=0; SELECT @counter:=@counter+1 AS Rank,LastName,Roll_no as Roll FROM Students ORDER BY Roll_ 执行

  • mysql分组取每组前几条记录(排名) 附group by与order by的研究

    --按某一字段分组取最大(小)值所在行的数据 复制代码 代码如下: /* 数据如下: name val memo a 2 a2(a的第二个值) a 1 a1--a的第一个值 a 3 a3:a的第三个值 b 1 b1--b的第一个值 b 3 b3:b的第三个值 b 2 b2b2b2b2 b 4 b4b4 b 5 b5b5b5b5b5 */ --创建表并插入数据: 复制代码 代码如下: create table tb(name varchar(10),val int,memo varchar(20)

  • Mysql排序获取排名的实例代码

    代码如下所示: SELECT @i:=@i+1 rowNum, if(@total=t.s_score,@rank,@rank:=@i) rank,@total:=t.s_score, t.* from( select t1.* ,t2.s_score from student t1 LEFT JOIN score t2 on t1.s_id=t2.s_id and t2.c_id="01" ORDER BY t2.s_score desc )t,(select @i:=0,@rank

  • MySQL页面访问统计及排名情况

    MySQL页面访问统计及排名情况 统计访问页面数量,以分辨率进行排名 SELECT CONCAT(`height` , '*', `width`) AS `resolution` , COUNT(CONCAT(`height`, '*', `width`)) AS `total` FROM `wifi_status_page` GROUP BY CONCAT(`height`, '*', `width`) ORDER BY `total` DESC LIMIT 0 , 30 最近7天页面访问量,

  • MySQL窗口函数实现榜单排名

    目录 rank() dense_rank() row_number() rank()函数的模拟实现 dense_rank()的模拟实现 row_number的模拟实现 总结 相信大家在日常的开发中经常会碰到榜单类的活动需求,通常在榜单中都会要求返回排名,今天我们就用MySQL的窗口函数来快速实现一下 首先,先建一个测试表 create table praise_record( id bigint primary key auto_increment, name varchar(10), prai

  • MySQL窗口函数的具体使用

    目录 一.什么是窗口函数 1.怎么理解窗口? 2.什么是窗口函数 二.窗口函数用法 1.序号函数:row_number() / rank() / dense_rank() 2.分布函数:percent_rank() / cume_dist() 3.前后函数:lag(expr,n) / lead(expr,n) 4.头尾函数:FIRST_VALUE(expr).LAST_VALUE(expr) 5.其他函数:nth_value() / nfile() 本章小结   之前我给粉丝们搞过个投票,寻找M

  • Python爬虫之对CSDN榜单进行分析

    前言 本篇文章的主要内容是利用Python对CSDN热榜变冷榜的指标数据进行分析的爬虫 分析一下各指标 开始爬取热榜,请稍候...耗时:2.199401808s [Top100指标统计] 浏览为0的:        3评论为0的:       76收藏为0的:       51浏览评论0的:    3三指标都0的:    2 浏览个位数的:    25评论个位数的:    98收藏个位数的:    86无封面题图的:    74 浏览>=100的:    18评论>=10的:      1收藏

  • 编程语言榜单Java与Python并列第二!Julia下滑

    目录 RedMonk 编程语言排行榜 TOP 20 值得关注的变化 Java TypeScript Go/Kotlin/Rust Dart Julia 近日,全球知名行业分析公司 RedMonk 发布了 Q3 的编程语言榜单,本排行榜基于 GitHub 和 Stack Overflow 两大社区中使用及讨论的编程语言热度进行排行,真实地反应了开发者对各大编程语言应用的现状,也希望透过此榜单能够为更多的从业者在工具的抉择层面带来一些借鉴. RedMonk 编程语言排行榜 TOP 20 通过调查与分

  • python爬取酷狗音乐Top500榜单

    目录 网页情况 python 代码 运行效果 总结 网页情况 爬取数据包含 歌曲排名.歌手.歌曲名.歌曲时长 python 代码 import requests #请求网页获取网页数据 from bs4 import BeautifulSoup #解析网页数据 import time #时间库 #user-Agent,伪装成浏览器,便于爬虫的稳定性 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64;

  • MySQL窗口函数OVER()用法及说明

    目录 MySQL窗口函数OVER() 下面的讲解将基于这个employee2表 MySQL窗口函数OVER() 下面的讲解将基于这个employee2表 mysql> SELECT * FROM employee2; +----+-----------+------+---------+---------+ | id | name | age | salary | dept_id | +----+-----------+------+---------+---------+ | 3 | 小肖 |

  • 详解MySQL 5.7 MGR单主确定主节点方法

    我们行MGR年底要上线了,每天都要看官方文档学习,做测试,坚持每天写一个小知识点,有想一起学习的么~ MySQL 5.7 MGR单主确定主节点是哪个,我们可以通过成员ID来判断,然后结合read_only参数来确认. [root@localhost ~]# mysql -uroot -p -P 3306 -h 127.0.0.1 mysql: [Warning] Using a password on the command line interface can be insecure. Wel

  • Python scrapy爬取起点中文网小说榜单

    一.项目需求 爬取排行榜小说的作者,书名,分类以及完结或连载 二.项目分析 目标url:"https://www.qidian.com/rank/hotsales?style=1&page=1" 通过控制台搜索发现相应信息均存在于html静态网页中,所以此次爬虫难度较低. 通过控制台观察发现,需要的内容都在一个个li列表中,每一个列表代表一本书的内容. 在li中找到所需的内容 找到第两页的url "https://www.qidian.com/rank/hotsale

  • mybatis调用mysql存储过程(返回参数,单结果集,多结果集)

    目录 一.接收一个返回值 注意事项: 存储过程主要分成三类: 二.接收list结果集 三.返回多个结果集 四.第二种配置也可以 一.接收一个返回值 使用Map接收返回参数,output参数放在传入的param中 创建表 DROP TABLE IF EXISTS `demo`; CREATE TABLE `demo` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`

随机推荐