题目来源
题目内容
编写一个 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 |
+——-+——+
解答
SELECT
a.score AS Score,
CASE
WHEN @prescore = a.score THEN
CONVERT(@rank, UNSIGNED)
WHEN @prescore != (@prescore := a.score) THEN
CONVERT((@rank := @rank + 1 ), UNSIGNED)
END as Rank
FROM
(SELECT score from rank) a,
(SELECT @rank:=0, @prescore:=-1) b
ORDER BY
a.score DESC;
说明:
此处采用了自定义变量的解决方式,自定义变量需要加上@符号以表明是一个自定义变量。此处的自定义变量有2个:
- @rank: 排名顺序
- @prescore:记录上一个分值。如果当前分值等于上一个分值,则说明是并列关系,@rank的值不变(对应代码的WHEN @prescore = a.score THEN);否则,需要为@prescore赋值成当前值,并且@rank的值加1(对应代码的@prescore != (@prescore := a.score))。
@prescore != (@prescore := a.score)说明:
功能:当@prescore=a.score的时候返回false;不等的时候返回true
代码说明:此处不好理解的话,可以写一段java代码说明。代码如下
public class Test {
public static void main(String[] args) {
int a = 5;
System.out.println( a != (a = 6)); // true
System.out.println( a != (a = 6)); // false
}
}