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进行倒序展现;

相关文章
相关标签/搜索