You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel分组展示每组胜场最多的前2支球队问题

嘿,这个世界杯小组赛的展示需求我之前帮朋友踩过类似的坑,咱们一步步来搞定它!

先搞定核心查询:取每组胜场最多的前2队

你之前用take(2)+groupBy没用,是因为SQL里groupBy是先聚合再排序,根本没法拿到每组的topN。这时候窗口函数才是正确的打开方式,不管你用原生SQL还是Laravel这类框架,底层逻辑都是一样的。

假设你的数据结构(两种常见情况)

情况1:已经有胜场统计字段

如果你的数据库里已经有类似team_group_stats的表,存了year(年份)、group(小组)、team_id、wins(胜场数),那直接用窗口函数排名:

SELECT * FROM (
    SELECT 
        year,
        `group`,
        team_id,
        wins,
        -- 按年份+小组分组,胜场倒序排名
        ROW_NUMBER() OVER (PARTITION BY year, `group` ORDER BY wins DESC) AS rank
    FROM team_group_stats
) AS ranked_teams
WHERE rank <= 2

如果是Laravel,用Eloquent的话可以这么写:

$topTeams = DB::table('team_group_stats')
    ->selectRaw('*, ROW_NUMBER() OVER (PARTITION BY year, `group` ORDER BY wins DESC) as rank')
    ->having('rank', '<=', 2)
    ->get();

情况2:只有比赛记录,需要计算胜场

如果你的数据是存在matches表(每场比赛的记录,字段比如year, group, home_team_id, away_team_id, home_score, away_score),那得先统计每个球队的胜场,再排名:

SELECT * FROM (
    SELECT 
        year,
        `group`,
        team_id,
        wins,
        ROW_NUMBER() OVER (PARTITION BY year, `group` ORDER BY wins DESC, goal_difference DESC) AS rank
    FROM (
        -- 先统计每个球队的胜场和净胜球(处理同分情况)
        SELECT 
            year,
            `group`,
            team_id,
            COUNT(*) AS wins,
            SUM(goal_diff) AS goal_difference
        FROM (
            -- 主场获胜的球队
            SELECT 
                year,
                `group`,
                home_team_id AS team_id,
                (home_score - away_score) AS goal_diff
            FROM matches
            WHERE home_score > away_score
            UNION ALL
            -- 客场获胜的球队
            SELECT 
                year,
                `group`,
                away_team_id AS team_id,
                (away_score - home_score) AS goal_diff
            FROM matches
            WHERE away_score > home_score
        ) AS team_results
        GROUP BY year, `group`, team_id
    ) AS team_wins
) AS ranked_teams
WHERE rank <= 2

这里加了goal_difference(净胜球)排序,是为了贴合世界杯的同分规则,避免排名逻辑不合理~

前端循环展示&高亮

拿到查询结果后,你可以先按年份分组,再按小组分组,然后遍历每个小组的前2球队。举个Laravel Blade的示例:

@foreach($topTeams->groupBy('year') as $year => $groupedData)
    <div class="world-cup-year">
        <h2>{{ $year }}年世界杯</h2>
        @foreach($groupedData->groupBy('group') as $groupName => $teams)
            <div class="group-section">
                <h3>{{ $groupName }}组 出线球队</h3>
                <ul class="team-list">
                    @foreach($teams as $team)
                        <!-- 按排名高亮:小组第一金色,小组第二银色 -->
                        <li class="team-item {{ $team->rank == 1 ? 'group-winner' : 'group-runner-up' }}">
                            {{ $team->name }} | 胜场:{{ $team->wins }} | 净胜球:{{ $team->goal_difference ?? 0 }}
                        </li>
                    @endforeach
                </ul>
            </div>
        @endforeach
    </div>
@endforeach

搭配简单的CSS样式:

.group-winner { color: #ffd700; font-weight: bold; }
.group-runner-up { color: #c0c0c0; font-weight: bold; }
要不要调整数据库结构?

分两种情况判断:

  • 如果你的比赛数据不多,每次查询计算胜场完全没问题,不用改结构,用上面的SQL查询就行。
  • 如果数据量很大(比如多年的海量比赛记录),或者查询频率很高,那建议加一个统计中间表(比如team_group_stats),每次新增/修改比赛记录时,同步更新这个表的胜场、净胜球等数据。这样每次查询直接读统计表,性能会提升很多,也避免了重复计算。

最后提醒一下:如果有球队胜场相同,一定要在ORDER BY里加上净胜球、进球数这类排序条件,完全贴合世界杯的出线规则,避免排名错误~

内容的提问来源于stack exchange,提问作者Bw70316

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:42:04