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

SQL聚合前如何去重?Rails多对多关联统计车队积分重复问题

问题根源

你遇到的统计翻倍问题本质是Season到Team的关联是通过driver_teams中间表实现,同一赛季同一车队如果绑定了N名车手,就会对应N条driver_teams记录。关联查询results时会把这N条中间表对应的积分全部累加,最终结果等于实际值乘以车队当前赛季的车手数量。你尝试的distinct是对最终返回结果去重,不会影响聚合阶段的计算逻辑,因此无效。

可用解决方案

方案1:子查询先筛选唯一车队再聚合(逻辑最直观,兼容性最好)

先通过子查询拿到当前赛季的唯一车队列表,再基于该列表统计积分,从根源避免重复数据参与计算:

# 先获取当前赛季所有唯一车队的ID子查询
season_teams_subquery = season.teams.select(:id).distinct

# 基于唯一车队列表统计当前赛季总积分
Team.where(id: season_teams_subquery)
    .joins(driver_teams: :results)
    .where(driver_teams: { season_id: season.id })
    .select('teams.*, SUM(results.points) AS points')
    .group('teams.id')

方案2:从中间表层聚合再关联车队(性能最优)

直接从DriverTeam中间表入手做第一次聚合,避免车队维度的重复关联:

# 先统计当前赛季每个车队的总积分
points_agg = season.driver_teams
                   .joins(:results)
                   .select('team_id, SUM(results.points) AS total_points')
                   .group(:team_id)

# 关联车队表获取完整字段
Team.joins("INNER JOIN (#{points_agg.to_sql}) agg ON teams.id = agg.team_id")
    .select('teams.*, agg.total_points AS points')

额外修正

注意你当前Result模型的关联拼写有误,though应该改为through,否则后续跨关联查询会报错:

class Result < ApplicationRecord
  belongs_to :driver_team
  has_one :driver, through: :driver_team # 修正拼写
  has_one :team, through: :driver_team # 修正拼写
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 04:57:01