【问题标题】:Advanced ActiveRecord Query: Filter Sum through Nested Associations高级 ActiveRecord 查询:通过嵌套关联过滤总和
【发布时间】:2016-08-25 18:45:27
【问题描述】:

假设我是一个具有以下数据库结构的电子商务网站:

  • Orders has_many OrderItems
  • OrderItem belongs_to Product
  • order_items 表有一个列,数量。
  • 产品表有一个 列,价格。

我想在我的 Order 模型中创建一个能够按总价过滤订单的范围。这是订单的总和(order_item 数量 * order_item 的产品价格)。

预期用途:

#Get orders that have a total cost greater than 10
Order.filter_cost('gt', 10)

这是我到目前为止形成的,但它似乎并不完全有效。我在想我不应该分组,但如果我不使用分组就会出错。在以下范围内,我得到了响应,但返回的集合不准确。

scope :filter_cost, (lambda do |*args|
  if args[0] && %w(gt lt et).include?(args[0]) && args[1]
    operator_map = { 'gt' => '>', 'lt' => '<', 'et' => '=' }
    joins(order_items: :product).group('orders.id').group('order_items.id').group('products.id').having("SUM(products.price * order_items.quantity) #{operator_map[args[0]]} ?", args[1].to_f)
  end
end)

我可以就我的查询有什么问题获得一些指导吗?

【问题讨论】:

    标签: ruby-on-rails postgresql activerecord


    【解决方案1】:
    def self.total_cost(direction, amount)
      select(orders.*, SUM(products.price * order_items.quantity) AS total_price).
      joins(order_items: :product).
      where(SUM(products.price * order_items.quantity) #{direction} #{amount})
    end
    

    现在您可以像Order.total_cost(:&gt;, 10) 一样使用它 附言- 你甚至可以访问total_amount,方法是调用它作为此查询返回的实例的方法。

    Like Order.total_cost(:&gt;, 10).first.total_cost(返回该项目的总成本)

    我认为使用符号而不是 gtlt 会更好,因为任何人都可以更直接地了解该方法的作用 + 您不必进行不必要的映射。

    可能不是最优雅的解决方案,但它确实有效。

    【讨论】:

      猜你喜欢
      • 2016-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-26
      • 2011-06-03
      • 2018-08-04
      • 1970-01-01
      相关资源
      最近更新 更多