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
相关产品推荐
相关产品推荐

