LeetCode_SQL_【178.分数排名】

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

Id Score
1 3.50
2 3.65
3 4.00
4 3.85
5 4.00
6 3.65

排序过后:

Score Rank
4.00 1
4.00 1
3.85 2
3.65 3
3.65 3
3.50 4

思考线路

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

你可能感兴趣的:(LeetCode)