题目:请你找出每个岗位分数排名前2名的用户,得到的结果先按照language的name升序排序,再按照积分降序排序,最后按照grade的id升序排序
结题思路:先对每个岗位的分数进行排名,然后取排名1、2的结果即可。但需要注意结果表中,JAVA语言出现3个用户,其中有两个分数一致,也就是说,分数一致排名相同且序号要连续,故这里要用dese_rank()排序
总结下3种常用排序窗口函数区别:
- row_number 会为查询出来的每一行记录生成一个序号,依次顺序排序且不会重复;
- rank rank与row_number不同的是,rank函数考虑到over子句中排序字段值相同的情况,over子句中排序字段值相同的序号是一样的,后面字段值不相同的序号将跳过相同的排名号排下一个;
- dense_rank 的功能与rank函数类似,dense_rank函数在生成序号时是连续的,而rank函数生成的序号有可能不连续。dense_rank函数出现相同排名时,将不跳过相同排名号,值紧接上一次的值。在各个分组内,rank()是跳跃排序,有两个第一名时接下来就是第三名,dense_rank()是连续排序,有两个第一名时仍然跟着第二名。
本题代码如下:
select id,name,score from ( select g.id,l.name,g.score, dense_rank() over(partition by l.name order by g.score desc)as rn from grade as g left join language as l on g.language_id=l.id )t where t.rn<=2 order by name,score desc,id