1. 程式人生 > >leetcode 178. 分數排名 【笛卡爾乘積】

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