User
和Organization
通过Relationship
建立了多对多关联。
Relationship
模型中的一个变量是一个名为member
的布尔值
user
模型可以多次出现Relationship
,因为user
可能与多个organizations
相关。
如何从所有users
中选择1)与任何organization
没有关系的随机实例(因此不会出现在Relationship
模型中)加上2)与组织有关系但users
所有与组织的关系的那些member = false
?
我想的是:
user = User.where( relationship_id = nil || ??? ).offset(rand(0..100)).first
答案 0 :(得分:2)
我会这样做
User.joins("LEFT JOIN relationships ON relationships.user_id = users.id").where('relationships.user_id IS NULL').offset(rand(0..100)).first
类似的东西:
member_ids = Relationship.where(member: true).pluck(:user_id).uniq
users = User.where.not(id: member_ids) # or User.where('id NOT in (?)', member_ids) on Rails < 4
答案 1 :(得分:1)
所以,你真正想要的是那些不是任何组织成员的用户,其中“成为成员”意味着“拥有一个成员=真的关系连接记录”。这比您指定的条件简单得多。
在那种情况下:
例如
member_ids = Relationship.where(member: true).distinct.pluck(:user_id)
@users = User.where("id not in (?)", member_ids).all
答案 2 :(得分:0)
获取没有组织的用户:
User.where.not(id: Relationship.pluck(:user_id).uniq)
如果没有一些逻辑可以将用户的总关系与member = false的关系进行比较,那么另一个查询似乎不是你可以做的事情。
答案 3 :(得分:0)
现在可以使用Where Exists宝石了。 (完全披露:我最近创造了这个宝石。)
# This will select all users, for which there are not relationships,
# or there is a relationship, but its 'member' attributes is false.
#
# Just what you've asked for.
users_to_select = User.where_not_exists(:relationships, member: true)
# 'offset' and 'count' will work as usual after 'where_not_exists'
random_user = users_to_select.offset(rand(users_to_select.count)).first
答案 4 :(得分:-1)
好吧,使用ActiveRecord并不认为您被禁止编写SQL代码。实际上,在许多情况下,您必需这样做。您的案例似乎是其中之一(您不能使用ActiveRecord进行'OR'查询,并且SQL'WHERE EXISTS'没有语法糖。)
所以我建议你这样做:
free_users = User.where("NOT EXISTS (SELECT 1 FROM relationships WHERE user_id = users.id) OR NOT EXISTS (SELECT 1 FROM relationships WHERE user_id = users.id AND member = FALSE)")
random_user = User.find(free_users.ids.sample)
有关SQL“EXISTS”的更多信息:
http://www.techonthenet.com/sql/exists.php
<强> UPD 即可。发布了另一个使用where_exists
gem的答案。