Postgres实现无重复rank()排名:骑行赛事数据场景问询
骑行赛事系列排名解决方案
针对你需要的「保留单场记录、同一选手同排名、同分留间隙」的排名需求,可以用单查询结合CTE(公共表表达式)实现,具体方案如下:
核心思路
先按选手维度计算总积分并生成符合要求的排名(同分留间隙),再将这个排名关联回原始的单场赛事记录,确保同一选手的所有记录共享相同排名。
示例SQL代码
假设你的赛事数据存储在race_results表中,包含字段:player_id(选手编号)、player_name(姓名)、race_id(赛事ID)、single_points(单场积分):
WITH player_totals AS ( SELECT player_id, player_name, SUM(single_points) AS total_points, -- 按总积分降序排名,同分共享排名且保留间隙 RANK() OVER (ORDER BY SUM(single_points) DESC) AS series_rank FROM race_results GROUP BY player_id, player_name ) SELECT rr.player_id, rr.player_name, pt.total_points, rr.single_points, rr.race_id, pt.series_rank FROM race_results rr INNER JOIN player_totals pt ON rr.player_id = pt.player_id ORDER BY pt.series_rank, rr.race_id;
方案说明
- CTE部分:先对选手分组,计算每个选手的总积分,同时用
RANK()函数生成系列排名——这个排名天然满足「同分留间隙」的要求(比如两位选手总积分相同,都会排第1,下一位直接排第3)。 - 关联查询:将原始单场记录和CTE结果关联,这样每个选手的每一条单场记录都会带上对应的系列排名,保证同一选手的所有记录排名一致。
- 为什么之前的方法不行:直接在包含单场记录的查询中使用
RANK(),会把同一选手的多条单场记录视为独立行,导致排名计算时出现不必要的跳号;而先分组计算选手总积分再排名,就规避了这个问题。
内容的提问来源于stack exchange,提问作者MysteriousFist
相关产品推荐
相关产品推荐

