使用`includes`而不是`joins`并使用sql`SUM`方法来避免N + 1

时间:2013-09-10 21:47:21

标签: mysql sql ruby-on-rails activerecord

我有一些旧的遗留代码,我添加了其他参数(我删除了不必要的部分):

Farm.joins("LEFT JOIN ( SELECT farm_id, SUM(kwota) as suma_wplat FROM payments GROUP BY farm_id) as kwoty ON kwoty.farm_id = farms.id").
      select("farms.id, kwoty.suma_wplat").includes(:certificate).where("certificates.data_wyslania IS null")

这将产生这样的查询:

"SELECT farms.id, kwoty.suma_wplat FROM `farms` LEFT JOIN ( SELECT farm_id, SUM(kwota) as suma_wplat FROM payments GROUP BY farm_id) as kwoty ON kwoty.farm_id = farms.id WHERE (certificates.data_wyslania IS null)"

不幸的是,由于suma_wplat以后不可用,因此会失败(返回的对象包含所有Farm属性)。

如果我将includes更改为joins,则生成的查询将如下所示:

 "SELECT farms.id, kwoty.suma_wplat FROM `farms` INNER JOIN `certificates` ON `certificates`.`farm_id` = `farms`.`id` AND `certificates`.`year` = '2013' LEFT JOIN ( SELECT farm_id, SUM(kwota) as suma_wplat FROM payments GROUP BY farm_id) as kwoty ON kwoty.farm_id = farms.id WHERE (certificates.data_wyslania IS null)"

现在Farm由适当的字段(以及计算的总和suma_wplat)组成,但会产生N + 1个查询。

我该如何解决?现在我只能考虑向Farm添加另一列的计数值,但这将是一种解决方法,而不是真正的解决方案。

编辑:整个查询现在看起来像这样:

Farm.joins("LEFT JOIN ( SELECT farm_id, SUM(kwota) as suma_wplat FROM payments GROUP BY farm_id) as kwoty ON kwoty.farm_id = farms.id").select("farms.id, kwoty.suma_wplat").map do |f|
  (...)
  f.suma_wplat
end

0 个答案:

没有答案