Mysql实现rank排名的3种写法
团队的绩效考核规则变化后,每周Bonus规则也发生了变化,排名前5的员工可以拿到Bonus。
为了使排名能够一目了然,小骨就考虑是否能在考核指标旁边加上“排名”字段。
虽然Mysql没有rank函数,但依然可以通过变量和if函数来实现排名功能!
变量功能请参考《》
随手摘了一段社群的积分表来做栗子,看着熟悉的名字好亲切[]~( ̄▽ ̄)~*
下面就由简到难地介绍Rank的3种写法!
SELECT id, name, score,
@curRank := @curRank+1 'rank'
FROM `tb_scores` ,
(SELECT @curRank := 0)r
ORDER BY score DESC
之前一直以为“:”是跟在变量后面表示赋值,今天才知道是“:=”表示赋值。
被自己蠢哭。
语句其实很简单,就是加了个curRank变量,根据score倒序,从1往后编号。
问题也很明显,如果score相同,不会对排名进行处理。
SELECT id,name,score, CASE
WHEN @preRank = score THEN @curRank
WHEN @preRank := score THEN @curRank:= @curRank+1
END 'rank'FROM `tb_scores` ,
(SELECT @curRank := 0, @preRank := NULL) r
ORDER BY score DESC
多引入了一个变量“preRank”来储存score,如果某个score与上个score相同,则用CASE WHEN给一个相同的“curRank”。
其实放在循环代码里挺好理解的,在Mysql里的写法总觉得怪怪的。
不习惯看CASE WHEN还可以用IF。
这里的IF函数和excel里的用法一样。
SELECT id,name,score,
IF(@preRank = score,@curRank,@curRank:= @curRank+1) 'rank'
FROM `tb_scores`,
(SELECT @curRank := 0, @preRank := NULL) r
ORDER BY score DESC
这里可以看到积分相同的小豆子和熊猫有了相同的排名,如果他俩占俩名次,那么苏菲应该排在第10名。
这种要怎么来写呢?
SELECT id,name,score,
@curRank:=IF(@preRank = score,@curRank,@curRank:= @incRank) 'rank',
@incRank:=@incRank +1,
@preRank:= score
FROM `tb_scores` ,
(SELECT @curRank := 0, @preRank := NULL,@incRank:=1) r
ORDER BY score DESC
再加入一个“incRank”变量来储存名次,进行占位。
从下图可以很清晰地到看到语句的工作逻辑。
如果只需要前四列,就在外层再套一层SELECT。
当把语句用到实际工作场景里,就变成了大型套娃现场。
让我不禁回想起学代码时三大经典语句之一:
禁止禁止套娃!