LeetCode_SQL_【178.分数排名】

问题描述:编写一个 SQL 查询来实现分数排名。如果两个分数相同,则两个分数排名(Rank)相同。请注意,平分后的下一个名次应该是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。
样例数据如下:

IdScore
13.50
23.65
34.00
43.85
54.00
63.65

排序过后:

ScoreRank
4.001
4.001
3.852
3.653
3.653
3.504

思考线路

sequenceDiagram
常规思路:dense_rank()->>Mysql模拟dense_rank()
特色思路:大喊一声:还有谁?懂了吗?O(∩_∩)O哈哈~

思路解析

1.常规方案:
根据问题描述,其表达的意思很符合Oracle中的一个排序函数dense_rank(),但Mysql中并不存在这样直接可以使用的函数。因此需要手动模拟。

手动模拟语句(市面上常见的语句):
select Score,
     case when @preScore = Score then @curerank
     else @curerank := @curerank + 1
     end as RANK,@preScore := Score AS preScore 
from Scores s,(select @curerank := 0,@preScore := NULL) r
order by Score desc

但上述的语句并不符合LeetCode的评判标准,因为其运行会产生如下的结果,注意在我的答案中的RANK数据是被视为字符,而非整型,因此我们需要将其格式进行转换。
这里写图片描述怎么转换的?外套一层+cast函数就可以。具体SQL可以参照下面:

select Score,CAST(RANK AS UNSIGNED) Rank 
from
(select Score,
     case when @preScore = Score then @curerank
     else @curerank := @curerank + 1
     end as RANK,@preScore := Score 
from Scores s,(select @curerank := 0,@preScore := NULL) r
order by Score desc) temp

2.特色方案:
就像在擂台上一样,很嚣张的喊道:还有谁?!!的感觉。其具体思路就是去重统计比当前分数还高的数据量,分数低的,比他高的人就多,那么反过来高手就寂寞了,count就少了,排名自然就高了。具体SQL如下,至于是用>搭配+1,还是>=看你的习惯,当然>=的效率是高于>的。

SELECT a.score,
  (SELECT count(DISTINCT score)
   FROM Scores
   WHERE Score > a.score)+1 AS rank
FROM Scores a
ORDER BY rank

总结:第一种方案是一种习惯性的思维导向,第二种则是一种活用规则的、非常灵巧的设计方案。个人还是很喜欢第二种方案,当然第一种的方案可以拓展你知识点的宽度。

参考博客:
1.常规思路_A
2.常规思路_B
3.特色思路_A

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值