簡體   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