1

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

class Order
  has_one :bill
  ...
end


class Bill
  has_many :rebills
  belongs_to :order

  ...
end

class Rebill
  belongs_to :bill
  ...
end

两者Bill都有Rebill一个status列,它可能处于多种状态之一,有些等同于成功,有些等同于失败。

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

如果一个Order有一个Bill失败的,一个Rebill也失败的,还有一个Rebill成功的,那么Order已经支付了,我对此不感兴趣。

如果 anOrder有一个Billthat failed 并且没有关联Rebills,那么它没有成功付款,我对此感兴趣。

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

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

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

4

2 回答 2

0

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

# 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以防止检查方法(用于显示控制台返回值)加载集合。

于 2018-10-28T19:34:37.207 回答
0

没那么复杂。首先,让我们找到所有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)")

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

附上DB 小提琴。

于 2018-10-28T14:24:30.603 回答