題目描述
編寫一個 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)
個人感覺這個題解好理解多了,非常清晰明了。