如果其中一个关联数据的属性x的值为'a',我就会发现排除数据的问题。
示例:
class Order < ActiveRecord::Base
has_many :items
end
class Item < ActiveRecord::Base
belongs_to :order
validate_presence_of :status
end
查询应返回不具有 status ='付费'的项目的所有订单(状态!='付费')。
由于1:n关联,订单可以包含多个商品。其中一个Itmes可以具有status ='paid'。即使订单中的其他商品的状态与“已付款”不同,也必须从我的查询结果中排除这些订单。
我如何解决这个问题:
paid_items = Items.where(status: 'paid').pluck(:order_id)
orders_wo_paid = Order.where('id NOT IN (?)', paid_items)
是否有ActiveRecord解决方案,可以在一个查询中解决此问题。 或者还有其他方法可以解决这个问题吗?
我不是在寻找红宝石解决方案,例如:
Order.select do |order|
!order.items.pluck(:status).include?('paid')
end
感谢想法和灵感。
答案 0 :(得分:1)
你可以这样做:
Order.where('orders.id NOT IN (?)', Item.where(status: 'paid').select(:order_id))
如果您正在使用Rails 4.x,那么:
Order.where.not(id: Item.where(status: 'paid').select(:order_id))
答案 1 :(得分:1)
您感兴趣的查询如下,但使用activerecord创建将很难/不可读:
SELECT
orders.*
FROM
orders
LEFT JOIN
order_items ON orders.id = order_items.order_id
GROUP BY
order_items.order_id
HAVING
COUNT(DISTINCT order_items.id) = COUNT(DISTINCT order_items.status <> 'paid')
抱歉sql缩进,我不知道它的约定是什么。
使用rails(不幸的是为最重要的部分编写sql)的方法(根本不是最好的)将是以下内容:
Order.group(:order_id).joins("LEFT JOIN order_items ON orders.id = order_items.order_id")
.having("COUNT(DISTINCT order_items.id) = COUNT(DISTINCT order_items.status = 'paid')")
当然,您可以使用AREL来摆脱硬编码的sql,但在我看来,阅读起来并不容易。
您可以在此要点中创建一个lefts连接示例:https://gist.github.com/mildmojo/3724189