分数排名

编写一个 SQL 查询来实现分数排名。如果两个分数相同,则两个分数排名(Rank)相同。请注意,平分后的下一个名次应该是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。
+----+-------+
| 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    |
+-------+------+
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/rank-scores
 
方法一:
 
求出比s1.score大或相等的记录有多少条,把它作为一个相关嵌套子查询
#比s1.score大或相等的记录有多少条
SELECT s1.score,
(SELECT COUNT(DISTINCT s2.score) FROM Scores s2 
WHERE s2.score >= s1.score
) AS Rank 
FROM Scores s1 
ORDER BY s1.score DESC;

分析它的执行效率:对于每一条记录,都要到s2表中查询出所有score比s1.score大或相等的记录。在未排序的情况下,时间复杂度近似为平方级别。

因此可以在子查询中加入order by语句:

SELECT s1.score,
(SELECT COUNT(DISTINCT s2.score) FROM Scores s2 
WHERE s2.score >= s1.score
ORDER BY s2.score DESC
) AS Rank 
FROM Scores s1 
ORDER BY s1.score DESC;

执行效率有明显的提升。

 

参考大神的代码,持续做出改进:

#173 ms, 在所有 mysql 提交中击败了91.38%的用户
select s1.score,
(select count(*)+1 
from (select distinct score from Scores) s2 
where s2.score>s1.score) as Rank 
from Scores s1 order by Rank

他的代码在我的基础上,把执行效率又提升了一个档次。原因在于:

他的子查询是从一个更小的集合中得到的count值,也就是单单score的集合(使用了三层嵌套查询);而我的子查询是从全体记录中去筛选。

 

posted @ 2020-03-09 14:01  盛夏群岛  阅读(312)  评论(0)    收藏  举报