点击关注公众号,干货第一时间送达

了解过 "开窗" 的小伙伴,
对此题一定不陌生。
属于SQL查询中较为高级的一种语法,
十分好用,
面试的时候,也几乎是必考的。
今天题目的"开窗",要实现"组内排序"功能,
那必然就需要用到:
rank()、dense_rank()、row_number()
排序三剑客!
一,需求场景
请对每个学生,各科成绩进行排序,并显示排名。
结果如下:

不过,诸位仔细想过没有,
如果不同学科,成绩相同,排名怎么计算呢?
例如:
成绩相同,是显示一样的排名,还是不一样的排名呢?

这要看题意。
不过本题并未明确要求,
所以,两种结果都行。
区别在于,你使用的是哪种排序函数。
二,解决方案
【演示工具:Mysql8 + Navicat for Mysql】
(1)使用 rank() 排序函数
select t1.s_id, st.s_name, t1.s_score, t1.rk
from student st
join (
select
s_id,
s_score,
rank() over(partition by s_id order by s_score desc) as rk
from score
)t1
on st.s_id = t1.s_id
结果集:

相同数据,排名一样。
(2)使用 row_number() 排序函数
select t1.s_id, st.s_name, t1.s_score, t1.rk
from student st
join (
select
s_id,
s_score,
row_number() over(partition by s_id order by s_score desc) as rk
from score
)t1
on st.s_id = t1.s_id
结果集:

相同数据,排名不一样。
(3)使用 dense_number() 排序函数
(为了体现该函数效果,我们调整一下样本数据)

select t1.s_id, st.s_name, t1.s_score, t1.rk
from student st
join (
select
s_id,
s_score,
dense_rank() over(partition by s_id order by s_score desc) as rk
from score
)t1
on st.s_id = t1.s_id
结果集:

而如果再用 rank() 查询一次:
select t1.s_id, st.s_name, t1.s_score, t1.rk
from student st
join (
select
s_id,
s_score,
rank() over(partition by s_id order by s_score desc) as rk
from score
)t1
on st.s_id = t1.s_id
结果集:

懂了吗?
总结:
row_number() 是对组内每行数据依次加一个序号,相同数据,序号也不一样。
rank()、dense_rank() 对组内数据进行排序,添加序号,相同数据,序号一样,
但是 rank() 有排序跳跃,dense_rank() 没有排序跳跃。
(4)over() 函数介绍
over() 函数就是用于"开窗",
其实就是分组,然后对组内数据执行:
xx over() 【注:xx 表示执行函数】
xx 函数操作的。
语法:
xx over(partition by id)
可以理解为:group by id 后,对每个分组内,执行 xx 函数操作。

文章转载自皮皮克克,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




