mysql中的排名函数

主要介绍一下mysql里面的排名函数,涉及到的函数有以下几个:

rank()、dense_rank()、row_number()

1、准备工作

建立一个rank表:

create table rank(
	id int(10) not null primary key,
	name varchar(20) not null,
	score int(10) not null
);

插入一些数据:

insert into rank values(1,'a',100);
insert into rank values(2,'b',100);
insert into rank values(3,'c',95);
insert into rank values(4,'d',95);
insert into rank values(5,'e',95);
insert into rank values(6,'a',90);
insert into rank values(7,'a',89);

表及数据的截图:
在这里插入图片描述

2、rank() 函数

语法结构:

RANK() OVER (
    PARTITION BY <expression>[{,<expression>...}]
    ORDER BY <expression> [ASC|DESC], [{,<expression>...}]
) 

按照某字段的排序结果添加排名,但它是跳跃的、间断的排名

(1)若按照分数直接进行排序的话,例如按照score进行排名

两个并列第一名后,下一个是第三名。

SELECT score, rank() over(ORDER BY score desc) as 'Rank' 
FROM rank;

结果:

+------+---------+
| score|   Rank  |
+------+---------+
|  100 |       1 |
|  100 |       1 |
|  95  |       3 |
|  95  |       3 |
|  95  |       3 |
|  90  |       6 |
|  89  |       7 |
+------+---------+
7 rows in set (0.02 sec)

(2)若按照某个字段分区进行排序的话,例如按照name进行分区,根据分数进行排名:

SELECT name , 
	score ,
	rank() over(partition by name ORDER BY score desc) as 'Rank' 
	FROM rank;
  • 首先,PARTITION BY子句按姓名将结果集分成多个分区。
  • 然后,ORDER BY子句按分数对结果集进行排序。

结果:

+------+------+---------+
| name | score|   Rank  |
+------+------+---------+
|  a   |  100 |       1 |
|  a   |  90  |       2 |
|  a   |  89  |       3 |
|  b   |  100 |       1 |
|  c   |  95  |       1 |
|  d   |  95  |       1 |
|  e   |  95  |       1 |
+------+------+---------+
7 rows in set (0.02 sec)

3、row_number() 函数

MySQL ROW_NUMBER()从8.0版开始引入了功能。这ROW_NUMBER()是一个窗口函数或分析函数,它为从1开始应用的每一行分配一个序号

语法结构如下:

ROW_NUMBER() OVER (
    PARTITION BY <expression>[{,<expression>...}]
    ORDER BY <expression> [ASC|DESC], [{,<expression>...}]

例如还是根据分数进行排序

SELECT 
 row_number() OVER (
 ORDER BY score
 ) row_num,
 score
 FROM rank;

结果:

+-------+------+---------+
|row_num| score|   Rank  |
+------ +------+---------+
|  1    |  100 |       1 |
|  2    |  100 |       2 |
|  3    |  95  |       3 |
|  4    |  95  |       1 |
|  5    |  95  |       1 |
|  6    |  90  |       1 |
|  7    |  89  |       1 |
+-------+------+---------+
7 rows in set (0.02 sec)

其次,使用ROW_NUMBER()函数将行划分为所有列的分区。对于每个唯一的行集,将重新开始行号。

SELECT 
    id,
    name,
    ROW_NUMBER() OVER (PARTITION BY name ORDER BY name) AS row_num
FROM rank; 

结果:

+------+------+---------+
| id   | name | row_num |
+------+------+---------+
|    1 | a    |       1 |
|    2 | a    |       2 |
|    3 | a    |       3 |
|    4 | b    |       1 |
|    5 | c    |       1 |
|    6 | d    |       1 |
|    7 | e    |       1 |
+------+------+---------+
7 rows in set (0.02 sec)

4、dense_rank() 函数

dense 英语中指“稠密的、密集的”。dense_rank()是的排序数字是连续的、不间断。当有相同的分数时,它们的排名结果是并列的,例如,1,2,2,3。

语法结构:

DENSE_RANK() OVER (
    PARTITION BY <expression>[{,<expression>...}]
    ORDER BY <expression> [ASC|DESC], [{,<expression>...}]
) 

例如,还是根据成绩进行排名:

SELECT score, dense_rank() over(ORDER BY score desc) as 'Rank' 
FROM rank;

结果:

+------+---------+
| score|   Rank  |
+------+---------+
|  100 |       1 |
|  100 |       1 |
|  95  |       2 |
|  95  |       2 |
|  95  |       2 |
|  90  |       3 |
|  89  |       4 |
+------+---------+
7 rows in set (0.02 sec)

若按照某个字段分区进行排序的话,例如按照name进行分区,根据分数进行排名

SELECT name , 
	score ,
	dense_rank() over(partition by name ORDER BY score desc) as 'Rank' 
	FROM rank;
  • 首先,PARTITION BY子句按姓名将结果集分成多个分区。
  • 然后,ORDER BY子句按分数对结果集进行排名。

结果:

+------+------+---------+
| name | score|   Rank  |
+------+------+---------+
|  a   |  100 |       1 |
|  a   |  90  |       2 |
|  a   |  89  |       3 |
|  b   |  100 |       1 |
|  c   |  95  |       1 |
|  d   |  95  |       1 |
|  e   |  95  |       1 |
+------+------+---------+
7 rows in set (0.02 sec)

这数据可能不太明显,如果再插入一条数据:

insert into rank values(8,'a',90);

然后查询,结果如下,与rank函数执行的结果就可以看到区别了:

+------+------+---------+
| name | score|   Rank  |
+------+------+---------+
|  a   |  100 |       1 |
|  a   |  90  |       2 |
|  a   |  90  |       2 |
|  a   |  89  |       3 |
|  b   |  100 |       1 |
|  c   |  95  |       1 |
|  d   |  95  |       1 |
|  e   |  95  |       1 |
+------+------+---------+
7 rows in set (0.02 sec)

题外话

小潘的个人微信公众号【小潘学程序】,有兴趣可给个关注~

一起学习,一起成长

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐