分数排名
编写一个 SQL 查询来实现分数排名。如果两个分数相同,则两个分数排名(Rank)相同。请注意,平分后的下一个名次应该是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。
+----+-------+
| Id | Score |
+----+-------+
| 1 | 3.50 |
| 2 | 3.65 |
| 3 | 4.00 |
| 4 | 3.85 |
| 5 | 4.00 |
| 6 | 3.65 |
+----+-------+
| 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 |
+-------+------+
| 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
链接: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的集合(使用了三层嵌套查询);而我的子查询是从全体记录中去筛选。

浙公网安备 33010602011771号