求助:查询锦标赛近5年排名前6球队的SQL实现
解决按锦标赛年份分组取前6球队的SQL方案
嘿,我来帮你搞定这个分组取Top6的问题!你的现有SQL已经完成了表关联和年份筛选,但确实还差按年份分组并提取每组前6球队的关键步骤——这时候用窗口函数是最简洁高效的方案,几乎所有现代数据库(比如MySQL 8.0+、PostgreSQL、SQL Server)都支持这个功能。
完整SQL实现
我直接给你写好可运行的代码,再一步步解释逻辑:
WITH ranked_teams AS ( SELECT t.id AS team_id, t.name AS team_name, c.year AS championship_year, c.name AS championship_name, r.points, -- 按年份分组,积分降序排名;积分相同时用球队ID排序保证结果稳定 ROW_NUMBER() OVER (PARTITION BY c.year ORDER BY r.points DESC, t.id) AS rank_in_year FROM teams AS t INNER JOIN results AS r ON t.id = r.id_team INNER JOIN championship AS c ON c.id = r.id_championship WHERE c.year BETWEEN 2012 AND 2017 -- 你的年份筛选条件 ) SELECT * FROM ranked_teams WHERE rank_in_year <= 6 ORDER BY championship_year DESC, rank_in_year ASC;
关键逻辑解释
- CTE临时表(ranked_teams):先通过这个临时表计算出每支球队在对应锦标赛年份里的排名
- 窗口函数核心:
PARTITION BY c.year:把数据按年份拆分成独立分组,每个年份单独计算排名ORDER BY r.points DESC:按积分从高到低排序,积分越高排名越靠前t.id是可选的补充排序条件——如果出现多支球队积分相同的情况,用球队ID排序能保证排名结果唯一稳定
- 筛选Top6:最后从临时表里过滤出排名≤6的记录,再按年份降序、排名升序整理输出
关于排名函数的选择
如果你的需求是允许积分相同的球队共享排名(比如两支球队同积89分都排第1,下一支排第3),可以把ROW_NUMBER()替换成RANK();要是想让排名连续(同积分都排第1,下一支排第2),就用DENSE_RANK(),根据你的业务需求调整就行。
老版本数据库兼容方案(比如MySQL 5.x)
如果你的数据库不支持窗口函数,也可以用子查询实现,不过代码会繁琐一些:
SELECT t.id AS team_id, t.name AS team_name, c.year AS championship_year, c.name AS championship_name, r.points FROM teams AS t INNER JOIN results AS r ON t.id = r.id_team INNER JOIN championship AS c ON c.id = r.id_championship WHERE c.year BETWEEN 2012 AND 2017 AND ( SELECT COUNT(DISTINCT r2.points) FROM results AS r2 INNER JOIN championship AS c2 ON c2.id = r2.id_championship WHERE c2.year = c.year AND r2.points >= r.points ) <= 6 ORDER BY c.year DESC, r.points DESC;
这个方案通过子查询统计当前球队同一年份里积分≥它的不同积分值数量,来判断是否进入前6,不过性能比窗口函数差一些,优先推荐窗口函数方案。
内容的提问来源于stack exchange,提问作者WilsonPena
相关产品推荐
相关产品推荐

