我有一個模型用戶thats has_many user_entitlements。我想要獲得所有具有預覽屬性並且沒有用戶權利的用戶。Rails高級sql查詢
我的代碼是目前:
User.where("preview is not null").keep_if {|user| user.user_entitlements.empty?}
這是通過所有用戶的迭代,看他們是否有任何用戶權利。
有沒有一種方法可以在SQL中做到這一點,使其更有效率,避免必須通過每個用戶?
我有一個模型用戶thats has_many user_entitlements。我想要獲得所有具有預覽屬性並且沒有用戶權利的用戶。Rails高級sql查詢
我的代碼是目前:
User.where("preview is not null").keep_if {|user| user.user_entitlements.empty?}
這是通過所有用戶的迭代,看他們是否有任何用戶權利。
有沒有一種方法可以在SQL中做到這一點,使其更有效率,避免必須通過每個用戶?
您可以使用Arel構建一個利用NOT EXISTS
的查詢。
user_arel = User.arel_table
ue_arel = UserEntitlement.arel_table
User.where("preview is not null").where(
UserEntitlement.where(ue_arel[:user_id].eq(user_arel[:id])).exists.not
)
我正在你的架構中的假設,即UserEntitlement
包含user_id
列。
就更簡單了,你可以用includes
強制LEFT JOIN,然後檢查NULL:
User.includes(:user_entitlements).
where("users.preview IS NOT NULL AND user_entitlements.id IS NULL")
如果存在大量數據集,您將'often_'在'LEFT JOIN'上看到'NOT EXISTS'更好的性能。來源:http://explainextended.com/2009/09/15/not-in-vs-not-exists-vs-left-join-is-null-sql-server/編輯:澄清你_often_看到更好的表現,考慮下面的PinnyM的評論。 – 2013-05-01 18:04:24
@DanReedy,這將取決於DBMS和版本 - 只有查詢優化器可以確定將如何執行特定的查詢和分析。您鏈接的文章來自3.5年前,並且是SQL Server特有的。我不確定當前版本的MySQL(或SQL Server)在這方面是否更好,但需要確定。 – PinnyM 2013-05-01 18:10:59
@DanReedy,我更喜歡你的方法順便說一句,但是ActiveRecord會讓這些亂七八糟的東西寫出來。太糟糕了,沒有寶石可以將其作爲原生行爲添加,因爲這是一種相當常見的情況。也許有一天... – PinnyM 2013-05-02 14:22:18
Awesome-謝謝! – BC00 2013-05-01 16:41:46