我有一个模型用户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