MYSQL中rank()、row_number()和dense_rank()的区别
MYSQL中rank()、row_number()和dense_rank()的区别
一、准备
首先我们根据下列建表语句简历scores表
1 | CREATE TABLE `scores` ( |
然后插入几条数据
1 | INSERT INTO `scores` |
二、rank()函数
语法结构:
1 | RANK() OVER ( |
这是一个专门用来排名的函数,通过PARTITION BY进行分组,然后使用ORDER BY进行排序,ORDER BY和常规用法一样。
现在我们使用刚才建立的表进行一个成绩排名,如下:
1 | SELECT |
结果如下:
subject | score | score_rank |
---|---|---|
数学 | 4.00 | 1 |
数学 | 3.65 | 2 |
英语 | 4.00 | 1 |
英语 | 3.65 | 2 |
语文 | 3.85 | 1 |
语文 | 3.50 | 2 |
这里我们使用rank()函数进行分数排名,我们使用PARTITION BY subject
将数据通过学科分组,然后ORDER BY score DESC对成绩进行从高到低的排名。并且在row_number()和dense_rank(),PARTITION BY 和 ORDER BY 的用法相同。
但是如果我们不进行分组只对分数进行排名呢?如下所示
1 | SELECT |
结果如下:
score | score_rank |
---|---|
4.00 | 1 |
4.00 | 1 |
3.85 | 3 |
3.65 | 4 |
3.65 | 4 |
3.50 | 6 |
这里,我们可以发现,PARTITION BY是可以不写的,不写则不进行分组,row_number()和dense_rank()同理。
但是观察rank()排名的结果,我们发现,出现相同成绩时,两个并列第一名后,下一个是第三名,rank()是跳跃的、间断的排名
三、row_number()函数
因为在这里PARTITION BY分组用法相同,且没有太大研究性,所以下面将不再使用
ROW_NUMBER()从MYSQL 8.0版开始引入的功能,如果低于这个版本,请跳过
row_number()语法如下
1 | ROW_NUMBER() OVER ( |
和RANK() 用法一样
还是对分数进行排序
1 | SELECT |
结果如下
id | score | score_rank |
---|---|---|
3 | 4.00 | 1 |
5 | 4.00 | 2 |
4 | 3.85 | 3 |
2 | 3.65 | 4 |
6 | 3.65 | 5 |
1 | 3.50 | 6 |
观察可以发现,row_number()函数的排名是连贯的,即使出现相同的分数也分了一二名,那么他凭什么给相同分数分排名高低呢?也许你看到了前面的id规律,其实不然,这里的id只是方便你观察,毕竟有些人会拿字符串当id,所以按id分高低是不严谨的。其实row_number() 会给每一行按照数据库中的顺序,从1开始给每一行分配一个序号,在这里和我们的id恰好相同
四、dense_rank()
语法如下:
1 | DENSE_RANK() OVER ( |
和前者区别不大,直接分数排名
1 | SELECT |
结果如下:
score | score_rank |
---|---|
4.00 | 1 |
4.00 | 1 |
3.85 | 2 |
3.65 | 3 |
3.65 | 3 |
3.50 | 4 |
可以观察得到,dense_rank()的结果中的排序数字是连续的、不间断。当有相同的分数时,它们的排名结果是并列的