Sql 有没有更好的方法来计算此发票模型的总价值?

Sql 有没有更好的方法来计算此发票模型的总价值?,sql,ruby-on-rails,ruby,ruby-on-rails-4,activerecord,Sql,Ruby On Rails,Ruby,Ruby On Rails 4,Activerecord,我有一个发票模型,它与另一个购物车模型有一种关系 购物车有许多商品,每个商品都有一个带有价格属性的产品 我的做法如下: class Invoice < ApplicationRecord has_one :cart, dependent: :destroy belongs_to :user def self.total sum = 0.0 Cart.all.each do |c| sum += c.total_value end s

我有一个发票模型,它与另一个购物车模型有一种关系

购物车有许多商品,每个商品都有一个带有价格属性的产品

我的做法如下:

class Invoice < ApplicationRecord
  has_one :cart, dependent: :destroy
  belongs_to :user

  def self.total
    sum = 0.0
    Cart.all.each do |c|
      sum += c.total_value
    end
    sum
  end
end
分类发票
cart对象上的total_value方法如下所示:

class Cart < ApplicationRecord
  def total_value
    sum = 0.0
    line_items.each { |l| sum += l.product.price.present? ? l.product.price * l.quantity : 0.0 }
    sum
  end
end
class购物车
所以我的问题是,有没有一种更有效的方法来执行相同的计算,可能是基于sql查询而不是数组操作? 它的效率有多高? 我也知道我的数组操作很差,那么如何以更ruby的方式实现同样的结果呢?

是否有更有效的方法来执行相同的计算 基于sql查询而不是数组操作

对。SQL比Ruby快得多,几乎无法与之相比:

  def self.total
    Cart.joins(line_items: :product)
        .sum('COALESCE(products.pharmacy_price * line_items.quantity, 0.0)')
  end
但我认为您可能需要的是单个
购物车
总计
,而不是所有
购物车
,它将是一个实例方法,而不是类实例方法:

因此,用法将是
Invoice.first.total
,而不是
Invoice.total

至于
total\u value
方法,您可以使用ActiveRecord级别的计算来编写,而不是Ruby,Ruby可能更快:

  def total_value
    self.class
        .joins(line_items: :product)
        .where(line_items(cart_id: id))
        .sum('COALESCE(products.pharmacy_price * line_items.quantity, 0.0)')
  end
至于

我也知道我的数组操作很差,所以我怎么能 以更ruby的方式实现相同的结果

您可以使用:

是否有更有效的方法来执行相同的计算 基于sql查询而不是数组操作

对。SQL比Ruby快得多,几乎无法与之相比:

  def self.total
    Cart.joins(line_items: :product)
        .sum('COALESCE(products.pharmacy_price * line_items.quantity, 0.0)')
  end
但我认为您可能需要的是单个
购物车
总计
,而不是所有
购物车
,它将是一个实例方法,而不是类实例方法:

因此,用法将是
Invoice.first.total
,而不是
Invoice.total

至于
total\u value
方法,您可以使用ActiveRecord级别的计算来编写,而不是Ruby,Ruby可能更快:

  def total_value
    self.class
        .joins(line_items: :product)
        .where(line_items(cart_id: id))
        .sum('COALESCE(products.pharmacy_price * line_items.quantity, 0.0)')
  end
至于

我也知道我的数组操作很差,所以我怎么能 以更ruby的方式实现相同的结果

您可以使用:


我想你应该在
购物车
表中添加
总值
列,在
行项目
表中添加
价格
列。我更喜欢动态计算,而不是存储它们。你为什么要计算购物车。我认为你应该只计算当前的购物车。我喜欢下面Andrey的回答,但为了回应你对数组操作的评论,当我需要对ruby数组操作进行复习时,请查看我反复阅读的这篇博文:我认为你应该将
total\u value
列添加到
carts
表中,将
price
列添加到
line\u项
表中。我更喜欢动态计算它们,而不是存储它们。为什么你这么做算了吧。我认为你应该只计算当前的购物车。我喜欢下面Andrey的答案,但为了回应你对数组操作的评论,请查看我在需要更新ruby数组操作时反复阅读的这篇博客文章: