leetcode 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 |
===資料庫 mysql
== 表的結構 Scores
欄位 | 型別 | 空 | 預設 |
---|---|---|---|
Id | int(11) | 是 | NULL |
Score | decimal(3,2) | 是 | NULL |
== 轉存表中的資料 Scores
建立SQL程式碼
Create table If Not Exists Scores (Id int, Score DECIMAL(3,2))
Truncate table Scores
insert into Scores (Id, Score) values ('1', '3.5')
insert into Scores (Id, Score) values ('2', '3.65')
insert into Scores (Id, Score) values ('3', '4.0')
insert into Scores (Id, Score) values ('4', '3.85')
insert into Scores (Id, Score) values ('5', '4.0')
insert into Scores (Id, Score) values ('6', '3.65')
以下從尾開始拆步
1.
select s1.Score as Score, count(s2.Score) as Rank from Scores as s1 left join (select distinct Score from Scores) as s2 on s1.Score <= s2.Score group by s1.id order by s1.Score desc
這是最終解答
去重將score分數找出來
s1和s2比較,選擇s1.score<=s2.score的記錄數,即為rank
按照id分組,再按照s1.score排序組,最後倒序
2.
select s1.Score as Score, count(s2.Score) as Rank from Scores as s1 left join (select distinct Score from Scores) as s2 on s1.Score <= s2.Score group by s1.id order by s1.Score
去掉倒序
3.
select s1.Score as Score, count(s2.Score) as Rank from Scores as s1 left join (select distinct Score from Scores) as s2 on s1.Score <= s2.Score group by s1.id
去掉score排序
4.
select * from Scores as s1 left join (select distinct Score from Scores) as s2 on s1.Score <= s2.Score
選擇所有不重複的Score資料,組成新表s2。
(select distinct Score from Scores) as s2;
級聯Scores表和s2表,級聯的條件是Scores表的Score欄位值小於等於s2表Score欄位的值。
select * from Scores as s1 left join (select distinct Score from Scores) as s2 on s1.Score <= s2.Score;
s1和s2比較,選擇s1.score<=s2.score的記錄數,即為rank
例如:s2的4條score記錄都比s1的第一條score記錄大,那麼這4次比較記錄都會記錄下來生成同等表,
也就是s1.score從1行變成4行,同時這4行的id都是一樣的。
5.
select s1.Score as Score, count(s2.Score) as Rank from Scores as s1 left join (select distinct Score from Scores) as s2 on s1.Score <= s2.Score
沒有分組的情況下,只取一次,因為只有一組,並計算了這一組的s2.score
6.
select s1.Score as Score, (s2.Score) as Rank from Scores as s1 left join (select distinct Score from Scores) as s2 on s1.Score <= s2.Score group by s1.id
按id分組,rank不是計算而是直接s2.score的情況下,證明這時select是隻會取每組的第一行
另一中解法就是使用使用者變數
SELECT
Score,
@rank := @rank + (@prev <> (@prev := Score)) Rank
FROM
Scores,
(SELECT @rank := 0, @prev := -1) init
ORDER BY Score desc