测试数据
drop table if exists t_exam;
create table t_exam
(
exam_id bigint auto_increment comment '主键id',
score tinyint comment '考试分数',
class_id bigint comment '班级id',
student_id bigint comment '学生id',
primary key (exam_id),
index (class_id, student_id, score)
) comment '考试分数';
insert into t_exam
values (default, 100, 1, 1),
(default, 80, 1, 2),
(default, 50, 1, 3),
(default, 50, 2, 4),
(default, 80, 2, 5),
(default, 30, 3, 6),
(default, 60, 3, 7),
(default, 80, 4, 8),
(default, 60, 4, 9),
(default, 40, 4, 10);
使用变量实现排名查询
基本知识:
- sql 语句中,使用
@
来定义一个变量。如:@rank
- sql 语句中,使用
:=
来给变量赋值,如:@rank:=0
,则变量rank
的值为0
利用变量实现排名查询:
-- 查询所有班级学生分数排名
select score as '考试分数', @rank := @rank + 1 as '排名'
from t_exam,
(select @rank := 0) as temp
order by t_exam.score desc;
查询结果:
考试分数 | 排名 |
---|---|
100 | 1 |
80 | 2 |
80 | 3 |
80 | 4 |
60 | 5 |
60 | 6 |
50 | 7 |
50 | 8 |
40 | 9 |
30 | 10 |
该方法存在的问题:
sql 语句复杂,相同分数排名不同,不公平。
使用MySQL窗口函数
rank 函数
查询语句:
select score as '考试分数', rank() over (order by score desc ) as '排名'
from t_exam;
查询结果:
考试分数 | 排名 |
---|---|
100 | 1 |
80 | 2 |
80 | 2 |
80 | 2 |
60 | 5 |
60 | 5 |
50 | 7 |
50 | 7 |
40 | 9 |
30 | 10 |
该方法存在的问题:
分数相同时,会并列排名,并且会出现排名间隙。
dense_rank 函数(推荐)
查询语句:
select score as '考试分数', dense_rank() over (order by score desc ) as '排名'
from t_exam;
查询结果:
考试分数 | 排名 |
---|---|
100 | 1 |
80 | 2 |
80 | 2 |
80 | 2 |
60 | 3 |
60 | 3 |
50 | 4 |
50 | 4 |
40 | 5 |
30 | 6 |
row_number 函数
查询语句:
select score as '考试分数', row_number() over (order by score desc ) as '排名'
from t_exam;
查询结果:
考试分数 | 排名 |
---|---|
100 | 1 |
80 | 2 |
80 | 3 |
80 | 4 |
60 | 5 |
60 | 6 |
50 | 7 |
50 | 8 |
40 | 9 |
30 | 10 |
该方法存在的问题:
sql 语句复杂,相同分数排名不同,不公平。