我的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
,筛选出与错误的订单匹配的所有用户出错。
然后我们再次加入orders
表,并且没有别名,只匹配users.id = orders.user_id
。如果没有orders.id
,那意味着用户在表格中根本没有任何订单,所以我们只想过滤掉只有orders.user_id IS NOT NULL
的用户,这意味着他们有订单。
你可以做这样的事情做这样的查询中轨:
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' } ])
这工作完美,真正学到了新的东西在这里!非常感谢。 – Hamza1510