题目描述
编写一个 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
分析
思考了几分钟,我毫无头绪~,于是我就去看评论,看到一个题解:
select s1.Score, count(distinct(s2.Score)) Rank from Scores s1, Scores s2 where s1.Score<=s2.Score group by s1.Id order by Rank;
想了几分钟,有点懵~,s1.Score<=s2.Score 是啥意思?
这个题解有好几个地方不明白是啥意思,当然关键点还是 where s1.Score<=s2.Score 不明白。
接下来我会在本地还原这个题解的执行过程,一步步分析 where s1.Score<=s2.Score 到底做了什么。
创建表 scores
CREATE TABLE `scores` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, `score` int(3) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
向表 scores 添加一些测试数据
INSERT INTO `scores` (`score`) values (100), (80), (80), (60);
查询scores表,目前共有4条记录
让我们来看看 select * from scores s1, scores s2 的返回结果是什么
返回的结果集共有16条记录。
这种多表查询又称 “笛卡尔查询",结果集的列数是s1
表和s2表的列数之和,行数是s1
表和s2
表的行数之积。
到了这里就会自然地想到: select * from scores s1, scores s2 where s1.score <= s2.score 的返回结果是什么呢?
这个结果是怎么得到的呢?我想到了这里大家应该都知道了
是的,如上图,左边是s1表,右边是s2表。
现在我们已经知道了 select * from scores s1, scores s2 where s1.score <= s2.score 的返回结果,再进行 group by,order by 和 count() 就很好分析了。
给 scores 表排名:
select s1.score, count(distinct(s2.score)) rank from scores s1, scores s2 where s1.score <= s2.score group by s1.id order by rank
group by s1.id:根据 s1.id 进行分组
count(distinct(s2.score)):distinct(s2.score)去重,count(distinct(s2.score))在分组的过程中计算 每个分组 对 s2.score去重后 的记录条数
分析到这里,我们已经清楚排名是怎么计算出来的了。但是,我们可能仍然会有一些疑惑,不禁会想:为什么这样做可以计算出排名?
思考
回想曾经考试后班级的排名,我们是怎么对学生进行排名的呢?
每个人都要和其他所有人进行比较,如果分数比所有人都高,则排第一名。
如下图,
可以看到, s1.score<=s2.score 就是对班级排名的一次过程模拟。
老实说,这个题解感觉不是那么好理解,或许是自己真的太笨了吧~
另一个题解
select a.Score as Score, (select count(distinct b.Score) from Scores b where b.Score >= a.Score) as Rank from Scores a order by a.Score DESC
作者:johnbear007
链接:https://leetcode-cn.com/problems/rank-scores/solution/fen-cheng-liang-ge-bu-fen-xie-hui-rong-yi-hen-duo-/
来源:力扣(LeetCode)
个人感觉这个题解好理解多了,非常清晰明了。