LeetCode-MySQL: 178.分數排名


題目描述

編寫一個 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)

個人感覺這個題解好理解多了,非常清晰明了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM