【数据库178】 分数排名

题目描述:(来源:力扣数据库178)

编写一个 SQL 查询来实现分数排名。如果两个分数相同,则两个分数排名(Rank)相同。请注意,平分后的下一个名次应该是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。

【数据库178】 分数排名_第1张图片

例如,根据上述给定的 Scores 表,你的查询应该返回(按分数从高到低排列):

【数据库178】 分数排名_第2张图片


我的解法:

SELECT
	s3.Score,
	s4.rank 
FROM
	Scores s3
LEFT JOIN ( #左连接
	SELECT
		s2.Score,
	IF(#if判断,设置rank_num等级值
		@rank_num < ( SELECT COUNT( DISTINCT Score ) FROM Scores ORDER BY Score DESC ),
		@rank_num := @rank_num + 1,
		NULL ) AS Rank 
	FROM( 
		SELECT DISTINCT s1.Score 
		FROM Scores s1, ( SELECT @rank_num := 0 ) t #初始化rank_num值
		ORDER BY Score DESC ) s2 
	) s4 
ON s3.Score = s4.Score 
ORDER BY s4.rank;

步骤详解:

  1. 先对Scores表按照Score列进行去重,并降序排列;
#这里方便程序的理解,我使用了自定义变量;
#但是在leetcode中使用下面的的方式定义自定义变量会报错,
#在leetcode中可以使用上面我写的方法。

SET @rank_num:=0;#rank等级值
#去重后的表中记录数
SET @count:=(SELECT COUNT(DISTINCT Score) FROM Scores ORDER BY Score DESC);

SELECT s2.Score,IF(@rank_num< @count,@rank_num:=@rank_num+1,NULL) as rank
FROM(
	SELECT DISTINCT s1.Score
	FROM Scores  s1
	ORDER BY Score DESC
) s2 ;

运行结果:
【数据库178】 分数排名_第3张图片

  1. 将原来的Scores表上面输出的临时表进行左连接,以两个表的Score字段作为连接条件,这样就可以知道原来的表中每一个Score的对应等级;
SET @rank_num:=0;
SET @count:=(SELECT COUNT(DISTINCT Score) FROM Scores ORDER BY Score DESC);

SELECT * #查询所有字段
FROM Scores  s3
LEFT JOIN#左连接
(
	SELECT s2.Score,IF(@rank_num< @count,@rank_num:=@rank_num+1,NULL) as rank
	FROM(
		SELECT DISTINCT s1.Score
		FROM Scores  s1
		ORDER BY Score DESC
	) s2 
) s4
ON s3.Score=s4.Score;#连接条件:分数值相等

运行结果:
与前面第一步对应来看,这里的rank就是左连接后,原来的表所对应的rank值。
【数据库178】 分数排名_第4张图片

  1. 经过前面两步,已经得到了rank值,现在只需要将其排序,然后提取相应的字段输出即可。这里按照rank值升序排列。
SET @rank_num:=0;
SET @count:=(SELECT COUNT(DISTINCT Score) FROM Scores ORDER BY Score DESC);

SELECT s3.Score,s4.rank
FROM Scores  s3
LEFT JOIN#左连接
(
	SELECT s2.Score,IF(@rank_num< @count,@rank_num:=@rank_num+1,NULL) as Rank
	FROM(
		SELECT DISTINCT s1.Score
		FROM Scores  s1
		ORDER BY Score DESC
	) s2 
) s4
ON s3.Score=s4.Score;#连接条件:分数值相等
ORDER BY s4.rank;#排序

运行结果:
【数据库178】 分数排名_第5张图片


在leetcode题解中看到一个比较简单的方法,比较巧妙。
主要思路:使用大于或等于当前这个分数的不重复的分数的数量作为排名。

select 
    a.Score as score , 
    (
	    select count(distinct b.Score) 
	    from Scores b 
	    # 条件是这个分数不小于我,因为a、b表数据相同,所以排名值最小是1
	    where b.Score >=a.Score
    ) as rank # 统计b表符合条件的不重复的分数的数量作为排名
from Scores a 
order by Score DESC; # 最后按分数(跟排名一样)降序排列

作者:zazalumonster
链接:https://leetcode-cn.com/problems/rank-scores/solution/mysqlbi-jiao-hao-li-jie-de-yi-chong-xie-fa-by-zaza/

你可能感兴趣的:(leetcode)