leetcode178 分數排名 Rank Scores

編寫一個 SQL查詢來實現分數排名。若是兩個分數相同,則兩個分數排名(Rank)相同。請注意,平分後的下一個名次應該是下一個連續的整數值。換句話說,名次之間不該該有間隔優化

 

 

 建立表和數據:spa

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');

解法:code

1.按Id和Score分組。每組中,大於等於每一個Score的不一樣Score數目就是其排名。blog

select S1.Score,count(distinct S2.Score) as Rank
from Scores as S1 join Scores as S2 on (S1.Score <= S2.Score)
group by S1.Id,S1.Score
order by S1.Score desc

優化:table

先將表中不一樣的score所有取出來,以子查詢的方式完成。再與錶鏈接,求 「大於等於每一個Score的不一樣Score數目」 。依然要分組。class

SELECT s1.Score, COUNT(s2.score) AS `Rank`
FROM Scores s1
JOIN
    (
        SELECT DISTINCT Score
        FROM Scores
        ORDER BY Score DESC
    ) AS s2 
ON (s1.Score <= s2.Score)
GROUP BY s1.Id,s1.Score
ORDER BY s1.Score desc

 

注意:FROM子句中關係的屬性均可以在HAVING和SELECT子句中用彙集運算,可是隻有出如今GROUP BY子句中的屬性,才能以不彙集的方式出如今HAVING和SELECT子句中。變量

所以,上面的S1.ID能夠不出如今SELECT子句中,S1.SCORE能夠出如今SELECT子句中。其它字段不能以非彙集的方式出如今SELECT子句中。好比,S2.Score。select

2.將「大於等於每一個Score的不一樣Score數目」在子查詢中實現,並再也不分組。im

select S1.Score,
    (select count(distinct S2.Score) 
     from Scores as S2 
     where S1.Score <= S2.Score
    ) as Rank
from Scores as S1
order by S1.Score desc;

 3.輔助變量數據

select score, @ran := @ran + (@pre <> (@pre := Score)) as rank 
from scores,(select @ran := 0, @pre := -1)  
order by score desc; 
  1. @ran 相似在 Oracle 中的rownum,能夠在生成結果內附加上一列序列號,能夠近似理解爲查詢後加上行號;

  2. @ran := @ran + 1 其實是賦值,舊值+1變爲新值賦給@a;

  3. 實際上並無直接 @ran+1 那麼簡單,還要先去判斷分數是否與前一行相同,因此引入 @pre 來記錄:

    • 先將Score賦值給: @pre:= Score;
    • 而後判斷以前的 @pre 是否與賦值後的@pre 不相同 ==> (@pre <> (@pre := Score)) 「<>」 就是 "!=" 的意思;
    • 二者不一樣,判斷結果爲真,則取1; 二者相同,判斷結果爲假,取0, 最後再用 0或1 加上@ran 即爲當前行分數的排名;
  4. (select @ran:= 0, @pre := -1) t 爲初始化 @ran 和 @pre 的開始值;

    • @pre 初始值爲 -1 爲的是防止Score有 0 分的出現;
    • @pre第一次比較Score值的時候,@pre 初始值確定和Score不一樣, 因此第一次比較 @ran 必然會 +1,因此@ran從0開始;
  5. 最後以將結果根據Score進行倒序展現;

相關文章
相關標籤/搜索