Leetcode NO.178. Rank Scores
178. Rank Scores
原题目链接:178. Rank Scores
这个题目没有官方提供的解法,本题主要参考以下链接的内容编写。
SQL 笔记:Leetcode#178 Rank Scores
写一条SQL查询语句进行分数的排名。如果两个分数相同,则应该具有相同的排名。在得分相同的排名之后,下一个排名的编号应该是下一个连续整数值。换句话说,在排名之间无“断点”。
+----+-------+ | Id | Score | +----+-------+ | 1 | 3.50 | | 2 | 3.65 | | 3 | 4.00 | | 4 | 3.85 | | 5 | 4.00 | | 6 | 3.65 | +----+-------+
比如,在上面的Scores表当中,你的查询应该产生如下报告(分数从高到低排序):
+-------+------+ | Score | Rank | +-------+------+ | 4.00 | 1 | | 4.00 | 1 | | 3.85 | 2 | | 3.65 | 3 | | 3.65 | 3 | | 3.50 | 4 | +-------+------+
Solution
方法一:采用子查询、JOIN语句和COUNT()函数[Accepted]
Algorithm
对于一个分数来说,它的排名就是去重后的Scores表中大于等于它的分数的数量。拿上面的表举例,表中有6个分数,3.50,3.65,4.00,3.85,4.00,3.65。去除重复记录,有4个分数,3.50,3.65,3.85,4.00。对于分数4.00,只有4.00 ≥ 4.00,排名为1。同样地,对于分数3.65,4.00 ≥ 3.65,3.85 ≥ 3.65,3.65 ≥ 3.65,有三个数大于等于它,所以排名为3。
MySQL
第一步,找出去重后的所有分数:
1 | SELECT DISTINCT Score FROM Scores; |
第二步,假设不重复的分数组成的表为t,接下来可以全连接t和Scores,然后对于Scores表中的每一个分数,找出t中大于等于它的分数:
1 | SELECT s.Score, t.Score FROM |
第三步,对Scores表中的每一个分数,统计t中大于等于它的分数的数量作为排名:
1 | SELECT s.Score, COUNT(t.Score) AS Rank FROM |
第四步,根据分数降序排序:
1 | SELECT s.Score, COUNT(t.Score) AS Rank FROM |
方法二:采用子查询和自定义变量[Accepted]
Algorithm
利用自定义变量的“左值”特性,即你在给这个变量赋值的同时也可以使用这个变量。这样可以实现这样的一种排名方式:直接按分数高低对成员进行排列,名次从1开始依次递增,当两个人分数相同的时候,也要按照出现的先后顺序或者其它规律分成先后。排序语句如下:
MySQL
1 | SELECT Score, @Counter := @Counter + 1 AS Rank |
排序结果如下:
+-------+------+ | Score | Rank | +-------+------+ | 4.00 | 1 | | 4.00 | 2 | | 3.85 | 3 | | 3.65 | 4 | | 3.65 | 5 | | 3.50 | 6 | +-------+------+
依题意,分数相同的排名也需要相同,因此这里还要使用DISTINCT关键字进行去重,然后先排出Score的名次保存在一个临时结果集当中,再跨原表和这个临时结果集匹配出各个Score对应的名次,实现本思路的SQL语句如下:
1 | SELECT A.Score, B.Rank |