一、题目来源
3252. 英超积分榜排名 II - 力扣(LeetCode)
二、数据表结构
表:TeamStats
+------------------+---------+ | Column Name | Type | +------------------+---------+ | team_id | int | | team_name | varchar | | matches_played | int | | wins | int | | draws | int | | losses | int | +------------------+---------+ team_id 是这张表的唯一主键。 这张表包含队伍 id,队伍名,场次,赢局,平局和输局。
三、需求
编写一个解决方案来计算联盟中每支球队的 得分,排名 和 等级。积分计算方式如下:
- 赢局 有
3
点得分 - 平局 有
1
点得分 - 输局 有
0
点得分
注意:积分相同的球队必须分配相同的排名。
等级评级:
- 根据积分将联盟分为
3
个等级: - 等级 1:前
33%
的队伍 - 等级 2:中间
33%
的队伍 - 等级 3:最后
34%
的队伍 - 如果等级边界出现平局,平局的队伍分配到更高的等级。
返回结果表以 points
降序 排序,然后以 team_name
升序 排序。
四、示例数据
输入:
TeamStats
表:
+---------+-------------------+----------------+------+-------+--------+ | team_id | team_name | matches_played | wins | draws | losses | +---------+-------------------+----------------+------+-------+--------+ | 1 | Chelsea | 22 | 13 | 2 | 7 | | 2 | Nottingham Forest | 27 | 6 | 6 | 15 | | 3 | Liverpool | 17 | 1 | 8 | 8 | | 4 | Aston Villa | 20 | 1 | 6 | 13 | | 5 | Fulham | 31 | 18 | 1 | 12 | | 6 | Burnley | 26 | 6 | 9 | 11 | | 7 | Newcastle United | 33 | 11 | 10 | 12 | | 8 | Sheffield United | 20 | 18 | 2 | 0 | | 9 | Luton Town | 5 | 4 | 0 | 1 | | 10 | Everton | 14 | 2 | 6 | 6 | +---------+-------------------+----------------+------+-------+--------+
输出:
+-------------------+--------+----------+---------+ | team_name | points | position | tier | +-------------------+--------+----------+---------+ | Sheffield United | 56 | 1 | Tier 1 | | Fulham | 55 | 2 | Tier 1 | | Newcastle United | 43 | 3 | Tier 1 | | Chelsea | 41 | 4 | Tier 1 | | Burnley | 27 | 5 | Tier 2 | | Nottingham Forest | 24 | 6 | Tier 2 | | Everton | 12 | 7 | Tier 2 | | Luton Town | 12 | 7 | Tier 2 | | Liverpool | 11 | 9 | Tier 3 | | Aston Villa | 9 | 10 | Tier 3 | +-------------------+--------+----------+---------+
解释:
- 谢菲尔德联队拿下 56 分(18 胜 * 3 分 + 2 平 * 1 分)位列第 1。
- 富勒姆拿下 55 分(18 胜 * 3 分 + 1 平 * 1 分)位列第 2。
- 纽卡斯尔联队拿下 43 分(11 胜 * 3 分 + 10 平 * 1 分)位列第 3。
- 切尔西拿下 41 分(13 胜 * 3 分 + 2 平 * 1 分)位列第 4。
- 伯恩利拿下 27 分(6 胜 * 3 分 + 9 平 * 1 分)位列第 5。
- 诺丁汉森林拿下 24 分(6 胜 * 3 分 + 6 平 * 1 分)位列第 6。
- 埃弗顿和卢顿镇均拿下 12 分,埃弗顿 2 胜 * 3 分 + 6 平 * 1 分,卢顿镇 4 胜 * 3 分。两支队伍并列位列第 7。
- 利物浦拿下 11 分(1 胜 * 3 分 + 8 平 * 1 分)位列第 9。
- 阿斯顿维拉拿下 9 分(1 胜 * 3 分 + 6 平 * 1 分)位列第 10。
等级计算:
- 等级 1:根据积分排名前 33% 的球队。谢菲尔德联队、富勒姆、纽卡斯尔联队和切尔西属于等级 1。
- 等级 2:中间 33% 的球队。伯恩利、诺丁汉森林、埃弗顿和卢顿镇属于等级 2。
- 等级 3:垫底 34% 的球队。利物浦和阿斯顿维拉落入等级 3。
五、分析
1.文字分析
第一步:计算每支球队的得分:wins*3+draws,再跟据球队得分的降序进行排名,积分相同的球队必须分配相同的排名,所以使用rank()函数进行排名;
第二步:获取参加比赛的球队总数;
第三步:使用case when进行条件判断,对每支球队进行等级划分。
2.图解
六、代码实现
with t1 AS (SELECTteam_name,wins * 3 + draws as points,rank() OVER (ORDER BY wins* 3 + draws desc) positionfrom TeamStats),t2 AS (SELECTcount(team_id) as totalfrom TeamStats
)
selectt1.*,(CASEwhen position <= ceiling(total * 0.33) THEN 'Tier 1'when position > ceiling(total * 0.33) and position <= ceiling(total * 0.66) then 'Tier 2'ELSE 'Tier 3'end) as tier
from t1,t2
ORDER BY points desc , team_name;
七、总结
本题需求为获取英超球队积分榜排名;
本题没有太难思考的点,唯一要注意的是在进行等级划分时,不可能将球队分割,所以要选择是向上取整还是向下取整,本题选择的是向上取整函数--ceiling()函数;
Ceiling() 函数是一个数学函数,用于向上取整。它返回大于或等于给定数字的最小整数。
语法为:ceiling(x),其中 x 是要进行向上取整操作的数值表达式,可以是一个数字、一个包含数字的列或者是一个能返回数字的表达式。
因为积分相同的球队必须分配相同的排名,所以要选择使用 rank() 排名函数,结果是 存在并列排名但排名不连续的。