题目描述:
编写一个 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 |+-------+------+
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');
解题思路:
oracle可以使用排名函数进行排名,因为名次之间不应该有“间隔”,所以要使用dense_rank()函数,这个函数排的名次是连续的,rank()函数会跳过(并列排名),mysql依然是使用自定义变量来进行排名。
解题方案:
oracle
select round(a.score,2) as score, b.rank from Scores a join (select a.*, rownum as rank from (select distinct a.score from Scores a order by a.score desc) a) b on a.score = b.score order by b.rank
mysql
SELECT ROUND(a.score, 2) AS score, b.rankFROM Scores aJOIN ( SELECT a.*, (@rowNum :=@rowNum + 1) AS rank FROM ( SELECT DISTINCT a.score FROM Scores a ) a, (SELECT(@rowNum := 0)) b ORDER BY a.score DESC) b ON a.score = b.scoreORDER BY b.rank