【问题标题】:Rails has_many where associated record meets a criteriaRails has_many 关联记录符合条件
【发布时间】:2018-10-28 14:16:59
【问题描述】:

在这个(简化的)系统中,

class Order
  has_one :bill
  ...
end


class Bill
  has_many :rebills
  belongs_to :order

  ...
end

class Rebill
  belongs_to :bill
  ...
end

BillRebill 都有一个 status 列,该列可能处于多种状态中的一种状态,有些等同于成功,有些等同于失败。

我目前正在尝试查找所有没有某种成功付款的Order 记录。如果关联的Bill 记录处于失败状态,并且Bill 记录有没有 关联的Rebill 记录处于成功,则订单符合我的标准状态。

如果一个Order 有一个失败的Bill,一个同样失败的Rebill,还有一个成功的Rebill,那么Order 已经付款,我对此不感兴趣.

如果Order 有一个失败的Bill 并且没有关联的Rebills,那么它没有成功付款,我对此感兴趣。

如果一个Order 有一个失败的Bill,并且任何数量的Rebills 处于失败状态(但没有一个处于成功状态),那么就没有成功支付,我 em> 对它感兴趣。

因此,我的问题是如何构造一个查询来返回所有没有某种成功付款的Order 记录?这里真正的问题是我持有在多个地方成功付款的概念,这很糟糕。但是,我觉得我应该能够低声说出正确的 SQL 咒语来做到这一点,但是 join 的数量,where's,have's 和 count's 让我难以置信!

任何人都知道我想在这里做什么,如果有的话,我会怎么做?

【问题讨论】:

    标签: sql ruby-on-rails postgresql activerecord


    【解决方案1】:

    没那么复杂。首先,让我们找到所有Order 记录,其中Bill 记录处于失败状态。

    Order.joins(:bill).where(bills: { state: "failed" })
    

    现在让我们确保对于Bill,不存在处于成功状态的Rebill

    Order.joins(:bill).where(bills: { state: "failed" })
         .where("NOT EXISTS(SELECT 1 FROM rebills 
                            WHERE bill_id = bills.id 
                            AND rebills.state = successful)")
    

    您也许可以用更 ActiveRecord 的方式编写 NOT EXISTS 查询,我通常放弃并使用原始 SQL。

    DB fiddle 已附上。

    【讨论】:

    • 我认为您可能错过了 EXISTS( 的右括号。
    【解决方案2】:

    这样的东西应该可以完成这项工作。

    # rebills contains all rebills with a successful payment
    rebills = Rebill.where(status: 'successful')
    # bills contains bills without a successful payment
    # that are not associated with the above described rebills 
    bills = Bill.where.not(status: 'successful', id: rebills.select(:bill_id))
    # orders contains orders that are associated with the above described bills
    orders = Order.where(id: bills.select(:order_id))
    

    orders被加载时,上面应该执行一个查询。

    注意:复制到控制台时,在行后缀;nil 以防止inspect 方法(用于显示控制台返回值)加载收藏。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-01
      • 2021-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-01
      • 1970-01-01
      相关资源
      最近更新 更多