繁体   English   中英

从所有订单均处于“错误”状态的订单中选择用户

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM