Rails4如何实现嵌套关联查询(contributions内连deposits左外连)并求和
实现方案
Rails 4 没有内置的left_outer_joins链式方法,你可以通过给joins方法传入原生SQL片段自定义连接规则,同时配合聚合函数完成需求,完整实现代码如下:
# 查询所有有contribution的Saving,计算关联的deposit总额,保留无deposit的记录 savings_with_total = Saving.select("savings.*, COALESCE(SUM(deposits.amount), 0) AS total_deposit_amount") .joins("INNER JOIN contributions ON contributions.saving_id = savings.id") .joins("LEFT OUTER JOIN deposits ON deposits.contribution_id = contributions.id") .group("savings.id")
代码说明
select部分除了加载Saving的全量字段,通过SUM(deposits.amount)计算存款总额,再用COALESCE函数把无存款记录的空值转换为0,避免出现nil结果- 第一个
joins写INNER JOIN逻辑关联contributions,符合你要求的「只保留存在contribution的Saving」的规则 - 第二个
joins写LEFT OUTER JOIN逻辑关联deposits,即使对应的contribution没有关联任何deposit,记录也不会被过滤 - 最后按
savings.id分组,保证每个Saving对应一条统计结果
额外优化
如果你后续需要遍历查询结果的关联contributions和deposits,为了避免N+1查询问题,可以在查询链上追加includes方法预加载关联数据:
savings_with_total = Saving.select("savings.*, COALESCE(SUM(deposits.amount), 0) AS total_deposit_amount") .joins("INNER JOIN contributions ON contributions.saving_id = savings.id") .joins("LEFT OUTER JOIN deposits ON deposits.contribution_id = contributions.id") .includes(contributions: :deposits) .group("savings.id")
使用方式
查询得到的Saving对象可以直接调用动态生成的total_deposit_amount属性获取存款总和:
savings_with_total.each do |saving| puts "储蓄计划#{saving.id}的总存款额:#{saving.total_deposit_amount}" end
内容的提问来源于stack exchange,提问作者Suganya Selvarajan
相关产品推荐
相关产品推荐

