[英]Selecting users from orders where all orders has the state “errored”
抱歉,这个问题令人困惑,因为我不确定如何提出该问题,但是我在这里:
我在Rails控制台中,尝试查找所有订单状态为“错误”且仅错误的所有用户。 用户有很多订单,每个订单的订单状态可以不同于“已完成”,“已退款”或“错误”。
User.includes(:orders).where(orders: { state: "errored" })
这将返回所有拥有一个或多个错误订单的用户,无论该用户是否也拥有其他状态的订单。 但是我正在尝试获取仅错误下单的用户。
我尝试了很多事情,从遍历每个用户的每个订单到尝试手动查找它们。 但这一定是更好的方法。
我的SQL不再是以前的样子,但我认为对于纯SQL解决方案,它需要看起来像:
SELECT "users".*
FROM "users"
LEFT JOIN orders on orders.user_id = users.id
LEFT JOIN orders non_errored_orders on non_errored_orders.user_id = users.id and non_errored_orders.state <> 'errored'
WHERE "non_errored_orders"."id" IS NULL AND "orders"."id" IS NOT NULL
所以,我们离开加入orders
表与别名non_errored_orders
,这将让这个如果是用户ID匹配和状态不等于出错的订单,行会出现(和non_errored_orders.id
将结束为NOT NULL
)。 然后,在where
子句中,仅过滤出non_errored_orders.id IS NULL
用户, non_errored_orders.id IS NULL
过滤出与未出错订单匹配的所有用户。
然后,我们再次离开users.id = orders.user_id
orders
表,仅在users.id = orders.user_id
上没有匹配的别名。 如果没有orders.id
,则意味着该用户在表中根本没有任何订单,因此我们只想过滤到orders.user_id IS NOT NULL
用户,这意味着他们拥有一个订单。
您可以通过以下方式在rails中进行如下查询:
User.
joins(:orders).
joins("LEFT JOIN orders non_errored_orders on non_errored_orders.user_id = users.id and non_errored_orders.state <> 'errored'").
where(non_errored_orders: { id: nil }).
where.not(orders: { id: nil }).distinct
# User Load (0.3ms) SELECT DISTINCT "users".* FROM "users" INNER JOIN "orders" ON "orders"."user_id" = "users"."id" LEFT JOIN orders non_errored_orders on non_errored_orders.user_id = users.id and non_errored_orders.state <> 'errored' WHERE "non_errored_orders"."id" IS NULL AND ("orders"."id" IS NOT NULL) LIMIT ? [["LIMIT", 11]]
# => #<ActiveRecord::Relation [#<User id: 1, ...>]>
在我非常有限的测试集中,这似乎是可行的。
测试数据原为
User.find(1).orders.create([ { state: 'errored' }, { state: 'errored' } ])
User.find(2).orders.create([ { state: 'errored' }, { state: 'completed' }])
User.find(3).orders.create([ { state: 'refunded' } ])
漫长而又简化的路径怎么样?
users_with_other_order_states = User.join(:orders).where.not(orders: { state: "errored" }).pluck(:id)
User.joins(:orders).where('orders.state = "errored" AND users.id NOT IN (?)', users_with_other_order_states)
我认为您可以尝试定义errored_orders
关系:
class User < ApplicationRecord
has_many errored_orders, ->{where state: 'errored'}
end
User.includes(:errored_orders).where(...)
希望能帮助到你!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.