Mysql常用函数之Rank排名函数详解

 更新时间:2024年01月04日 10:37:34   作者:pan_mlpan  
这篇文章主要介绍了Mysql常用函数之Rank排名函数详解,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

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)

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 使用mysqldump对MySQL的数据进行备份的操作教程

    使用mysqldump对MySQL的数据进行备份的操作教程

    这篇文章主要介绍了使用mysqldump对MySQL的数据进行备份的操作教程,示例环境基于CentOS操作系统,需要的朋友可以参考下
    2015-12-12
  • mysql视图之确保视图的一致性(with check option)操作详解

    mysql视图之确保视图的一致性(with check option)操作详解

    这篇文章主要介绍了mysql视图之确保视图的一致性(with check option)操作,结合实例形式详细分析了视图的一致性操作原理、实现技巧与操作注意事项,需要的朋友可以参考下
    2019-12-12
  • MySQL表复合查询的实现

    MySQL表复合查询的实现

    本文主要介绍了MySQL表的复合查询,如何使用多表查询、子查询、自连接、内外连接等复合查询的案例,感兴趣的可以了解一下
    2023-05-05
  • mysql 数据插入优化方法之concurrent_insert

    mysql 数据插入优化方法之concurrent_insert

    在MyISAM里读写操作是串行的,但当对同一个表进行查询和插入操作时,为了降低锁竞争的频率,根据concurrent_insert的设置,MyISAM是可以并行处理查询和插入的
    2021-07-07
  • MySQL 可扩展设计的基本原则

    MySQL 可扩展设计的基本原则

    可扩展设计是一个非常复杂的系统工程,所涉及的各个方面非常的广泛,技术也较为复杂,可能还会带来很多其他方面的问题。但不管我们如何设计,不管遇到哪些问题,有些原则我们还是必须确保的。
    2021-05-05
  • MYSQL主库切换binlog模式后主从同步错误的解决方案

    MYSQL主库切换binlog模式后主从同步错误的解决方案

    在使用FlinkSQL的mysql-cdc连接器来监听MySQL数据库时,通常需要将MySQL的binlog模式设置为ROW模式,当我们将MySQL主库的binlog模式从STATEMENT切换为ROW并重启MySQL服务后,MySQL从库在同步时可能会报错,所以本文介绍了MYSQL主库切换binlog模式后主从同步错误的解决方案
    2024-08-08
  • MySQL阻塞与死锁的解决

    MySQL阻塞与死锁的解决

    本文主要介绍了MySQL阻塞与死锁的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-09-09
  • MySQL语句加锁的实现分析

    MySQL语句加锁的实现分析

    MySQL的加锁分析,一直是一个比较困难的话题。我在工作过程中,经常会有同事咨询这方面的问题。今天我们来简单谈谈这个问题
    2017-10-10
  • Mysql删除重复的数据 Mysql数据去重复

    Mysql删除重复的数据 Mysql数据去重复

    这篇文章主要介绍了Mysql删除重复的数据 Mysql数据去重复,需要的朋友可以参考下
    2016-08-08
  • MySQL 数据库两台主机同步实战(linux)

    MySQL 数据库两台主机同步实战(linux)

    MySQL支持单向、异步复制,复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志文件,并维护日志文件的一个索引以跟踪日志循环。
    2009-04-04

最新评论