SQL技术问询:如何查询每个赛季进球最多的球队?
解决每个赛季进球最多球队的SQL查询问题
嘿,作为SQL新手,遇到JOIN和分组排序的问题太正常了,我来一步步帮你搞定这个需求!
先分析你原SQL的问题
你的语句有几个关键问题导致无法运行:
- 子查询里用的是
id_team,但外层查询写的是team_id,字段名不匹配,会直接报错 - 没有按
season分组,你要的是每个赛季的top球队,原语句只按球队分组,没法区分赛季 - 没有关联
team_table获取球队名称,也没处理“每个赛季取最大值”的核心逻辑
正确的查询思路
我们需要分两步走:
- 先把所有球队的进球数据按赛季+球队汇总(包含主场和客场的进球)
- 找出每个赛季的最大进球数,再匹配到对应的球队;或者用窗口函数直接给每个赛季的球队排名,取第一名
方法1:先汇总,再匹配赛季最大值
-- 第一步:汇总每个赛季每个球队的总进球 WITH team_season_goals AS ( SELECT mt.season, tt.team_name, SUM( CASE WHEN mt.home_team_id = tt.id_team THEN mt.home_team_goal ELSE mt.away_team_goal END ) AS total_goals FROM match_table mt -- 关联球队表,这里用INNER JOIN就够(因为比赛里的球队肯定在球队表中) JOIN team_table tt ON tt.id_team IN (mt.home_team_id, mt.away_team_id) GROUP BY mt.season, tt.id_team, tt.team_name ), -- 第二步:找出每个赛季的最大进球数 season_max_goals AS ( SELECT season, MAX(total_goals) AS max_goals FROM team_season_goals GROUP BY season ) -- 第三步:匹配得到每个赛季进球最多的球队 SELECT tsg.season, tsg.team_name, tsg.total_goals FROM team_season_goals tsg JOIN season_max_goals smg ON tsg.season = smg.season AND tsg.total_goals = smg.max_goals ORDER BY tsg.season;
方法2:用窗口函数(更简洁,推荐)
窗口函数ROW_NUMBER()可以帮我们按赛季分组,给每个球队的进球数排名,直接取排名第一的:
WITH team_season_goals AS ( SELECT mt.season, tt.team_name, SUM( CASE WHEN mt.home_team_id = tt.id_team THEN mt.home_team_goal ELSE mt.away_team_goal END ) AS total_goals, -- 按赛季分组,按进球数降序排名 ROW_NUMBER() OVER (PARTITION BY mt.season ORDER BY SUM( CASE WHEN mt.home_team_id = tt.id_team THEN mt.home_team_goal ELSE mt.away_team_goal END ) DESC) AS rank_num FROM match_table mt JOIN team_table tt ON tt.id_team IN (mt.home_team_id, mt.away_team_id) GROUP BY mt.season, tt.id_team, tt.team_name ) -- 取每个赛季排名第一的球队 SELECT season, team_name, total_goals FROM team_season_goals WHERE rank_num = 1 ORDER BY season;
关于JOIN类型的小解释
- INNER JOIN:只返回两个表中匹配成功的数据,这里因为
match_table里的球队ID肯定都在team_table里,所以用这个最适合,不会出现多余的NULL数据 - LEFT JOIN:返回左表(这里是
match_table)的所有数据,右表(team_table)匹配不到的会显示NULL,如果你的数据里可能存在球队表没有的ID,可以用这个,但一般比赛数据不会有这种情况 - RIGHT/FULL JOIN:这里完全用不上,RIGHT JOIN是返回右表所有数据,FULL是返回两个表所有数据,都不符合我们的需求
运行结果(对应你的示例数据)
| season | team_name | total_goals |
|---|---|---|
| 2008/2009 | C | 3 |
| 2009/2010 | B | 2 |
| 2011/2012 | E | 1 |
| 2012/2013 | B | 2 |
| 2012/2013 | E | 2 |
(注:2012/2013赛季B和E都进了2球,所以会返回两个结果,如果要只返回一个,可以把ROW_NUMBER()换成RANK()或者DENSE_RANK(),根据需求调整)
内容的提问来源于stack exchange,提问作者yoyo_24




