如何在轨道上急切加载儿童模型的红宝石总和值?

时间:2015-05-07 21:43:06

标签: ruby-on-rails rails-models

我有Order模型,它有很多items,看起来像这样

class Order < ActiveRecord::Base
  has_many :items

  def total
    items.sum('price * quantity')
  end
end

我有一个订单索引视图,像这样查询订单表

  def index
    @orders = Order.includes(:items)
  end

然后,在视图中,我访问了订单总数,因此,您会看到大量的SUM查询

SELECT SUM(price * quantity) FROM "items" WHERE "items"."order_id" = $1  [["order_id", 1]]
SELECT SUM(price * quantity) FROM "items" WHERE "items"."order_id" = $1  [["order_id", 2]]
SELECT SUM(price * quantity) FROM "items" WHERE "items"."order_id" = $1  [["order_id", 3]]
...

逐个加载order.total非常慢,我想知道如何通过单个查询以急切的方式加载总和,但我仍然可以像以前一样访问order.total

2 个答案:

答案 0 :(得分:0)

试试这个:

subquery = Order.joins(:items).select('orders.id, sum(items.price * items.quantity) AS total').group('orders.id')

@orders = Order.includes(:items).joins("INNER JOIN (#{subquery.to_sql}) totals ON totals.id = orders.id")

这将创建一个子查询,该子查询对订单总数进行求和,然后将该子查询加入到其他查询中。

答案 1 :(得分:0)

在此博客中,我使用find_by_sql或通过联接来解决此问题,为此我写了两个选择。

对于上面的示例,使用find_by_sql可以编写如下内容:

Order.find_by_sql("select
  orders.id,
  SUM(items.price * items.quantity) as total
from orders 
join items
   on orders.id = items.order_id
group by 
  order.id")

使用联接,您可以将其重写为:

Order.all.select("order.id, SUM(items.price * items.quantity) as total").joins(:items).group("order.id")

在select子句和group by子句中都将要在选择列表中包含的所有字段包括在内。希望有帮助!