leetcode 178. 分数排名 【笛卡尔乘积】

本文介绍了如何使用SQL解决LeetCode中的分数排名问题,通过笛卡尔乘积和左连接实现,确保相同分数的排名相同,且排名无遗漏。具体解决方案包括逐次去除不必要的排序和分组,最终提供了一个有效查询来获取按分数降序排列的排名。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

笛卡尔乘积其实就是两个表的级联

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

IdScore
13.50
23.65
34.00
43.85
54.00
63.65

例如,根据给定的上述 Scores 表,您的查询应该生成以下报告(按最高分排序):

ScoreRank
4.001
4.001
3.852
3.653
3.653
3.504

===数据库 mysql

== 表的结构 Scores

字段类型默认
Idint(11)NULL
Scoredecimal(3,2)NULL

== 转存表中的数据 Scores

创建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')

以下从尾开始拆步
1.

select s1.Score as Score, count(s2.Score) as Rank from Scores as s1 left join (select distinct Score from Scores) as s2 on s1.Score <= s2.Score group by s1.id order by s1.Score desc

这是最终解答
去重将score分数找出来
s1和s2比较,选择s1.score<=s2.score的记录数,即为rank
按照id分组,再按照s1.score排序组,最后倒序
这里写图片描述
2.

select s1.Score as Score, count(s2.Score) as Rank from Scores as s1 left join (select distinct Score from Scores) as s2 on s1.Score <= s2.Score group by s1.id order by s1.Score

去掉倒序
这里写图片描述
3.

select s1.Score as Score, count(s2.Score) as Rank from Scores as s1 left join (select distinct Score from Scores) as s2 on s1.Score <= s2.Score group by s1.id

去掉score排序
这里写图片描述
4.

select * from Scores as s1 left join (select distinct Score from Scores) as s2 on s1.Score <= s2.Score

选择所有不重复的Score数据,组成新表s2。

(select distinct Score from Scores) as s2;

级联Scores表和s2表,级联的条件是Scores表的Score字段值小于等于s2表Score字段的值。

select * from Scores as s1 left join (select distinct Score from Scores) as s2 on s1.Score <= s2.Score;

s1和s2比较,选择s1.score<=s2.score的记录数,即为rank
例如:s2的4条score记录都比s1的第一条score记录大,那么这4次比较记录都会记录下来生成同等表
也就是s1.score从1行变成4行,同时这4行的id都是一样的。
这里写图片描述
5.

select s1.Score as Score, count(s2.Score) as Rank from Scores as s1 left join (select distinct Score from Scores) as s2 on s1.Score <= s2.Score

没有分组的情况下,只取一次,因为只有一组,并计算了这一组的s2.score
这里写图片描述
6.

select s1.Score as Score, (s2.Score) as Rank from Scores as s1 left join (select distinct Score from Scores) as s2 on s1.Score <= s2.Score group by s1.id

按id分组,rank不是计算而是直接s2.score的情况下,证明这时select是只会取每组的第一行
这里写图片描述

另一中解法就是使用用户变量

SELECT
  Score,
  @rank := @rank + (@prev <> (@prev := Score))  Rank
FROM
  Scores,
  (SELECT @rank := 0, @prev := -1) init
ORDER BY Score desc
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值