【问题标题】:How to eager load child model's sum value for ruby on rails?如何在 Rails 上急切加载子模型的 ruby​​ 总和值?
【发布时间】:2015-05-07 21:43:05
【问题描述】:

我有一个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

【问题讨论】:

    标签: ruby-on-rails rails-models


    【解决方案1】:

    试试这个:

    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")
    

    这将创建一个对订单总数求和的子查询,然后将该子查询连接到您的其他查询。

    【讨论】:

      【解决方案2】:

      我在这篇关于使用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 子句中的选择列表中包含您想要的所有字段。希望有帮助!

      【讨论】:

        猜你喜欢
        • 2021-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-05
        • 2012-08-08
        • 1970-01-01
        • 2020-09-08
        相关资源
        最近更新 更多