編寫一個 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;
@ran 相似在 Oracle 中的rownum,能夠在生成結果內附加上一列序列號,能夠近似理解爲查詢後加上行號;
@ran := @ran + 1 其實是賦值,舊值+1變爲新值賦給@a;
實際上並無直接 @ran+1 那麼簡單,還要先去判斷分數是否與前一行相同,因此引入 @pre 來記錄:
(select @ran:= 0, @pre := -1) t 爲初始化 @ran 和 @pre 的開始值;
最後以將結果根據Score進行倒序展現;