Mysql排名窗口函数 RANK DENSE_RANK
-
-
- 先准备基础数据
- DENSE_RANK()
- RANK()
- 总结:
-
先准备基础数据
创建一个students表,主键id,字段score
create table students ( id bigint not null primary key, score double null ); -- 插入几条数据 INSERT INTO `students`(`id`, `score`) VALUES (1, 10); INSERT INTO `students`(`id`, `score`) VALUES (2, 30); INSERT INTO `students`(`id`, `score`) VALUES (3, 20); INSERT INTO `students`(`id`, `score`) VALUES (4, 20); INSERT INTO `students`(`id`, `score`) VALUES (5, 50); INSERT INTO `students`(`id`, `score`) VALUES (6, 30); INSERT INTO `students`(`id`, `score`) VALUES (7, 50); INSERT INTO `students`(`id`, `score`) VALUES (8, 90); INSERT INTO `students`(`id`, `score`) VALUES (9, 50);
最终表数据如下:
DENSE_RANK()
DENSE_RANK()是一个窗口函数,用于根据指定排序规则为每一行分配一个连续的排名值,即使有相同的排名也不会出现间隙。也就是说,如果有两行数据具有相同等级,则它们都会得到相同的排名,并且下一行的排名将紧跟在最高相同排名之后。
语法结构如下:
DENSE_RANK() OVER ( [PARTITION BY column1, column2, ... ] ORDER BY order_column1 ASC|DESC, order_column2 ASC|DESC, ... )
-
PARTITION BY :可选子句,用于将数据集分割成多个分区,在每个分区内部独立计算排名。 -
ORDER BY :指定用于确定排名顺序的列或表达式。默认是升序排列,也可以指定为降序排列。
例如示例中的
SELECT DENSE_RANK() OVER ( ORDER BY score DESC ) custom_rank, id, score FROM students
查询结果:
这样就返回每名学生的ID、分数以及基于分数从高到低的连续排名。如果两个或更多的学生得分相同,他们将获得相同的排名,且下一个不同分数的学生的排名不会因为之前的并列而跳跃。
RANK()
MySQL中的
具体语法结构如下:
SELECT student_id, class, score, RANK() OVER ( PARTITION BY class ORDER BY score DESC ) as rank_in_class FROM student_scores;
-
PARTITION BY (可选):用于将数据分割成多个分区,在每个分区内部进行独立排名。 -
ORDER BY :用于确定在每个分区内部如何排序行,这将决定排名的依据。 -
RANK() :窗口函数,它会根据ORDER BY 子句定义的顺序给每行分配一个唯一的排名。
以students表为例,想查询每个学生的分数进行降序排名,可以这样写查询:
SELECT RANK() OVER ( ORDER BY score DESC ) custom_rank, id, score FROM students
查询结果:
在这个例子中,RANK()函数将会为每个班级内的学生按分数从高到低分配一个排名,如果有分数相同的学生,则他们的排名也会相同,但后续学生的排名将会跳跃(比如如果第一名有两个,则第二名将是第三名)。
总结:
- RANK() 函数
-
当有多行具有相同的排序值时,
RANK() 函数会给这些行赋予相同的排名,但会导致后续行的排名出现跳跃。 -
例如,上方示例中又3个50分,之后才是30分,
RANK() 将分别为它们分配排名2和5,跳过了排名 3,4。
- DENSE_RANK() 函数
-
同样当有多行具有相同的排序值时,
DENSE_RANK() 函数也会赋予相同的排名,但不同的是,它不会跳过任何排名,而是让后续行的排名紧随其后。 -
对于上述相同的例子,如果使用
DENSE_RANK() ,则三行成绩将分别得到排名1和3没有排名间的跳跃。
总结起来:
-
RANK() 会产生非连续的排名(即有空缺的排名)。 -
DENSE_RANK() 则始终保持排名的连续性,即使在相同值的情况下也不会产生排名空缺。