【问题标题】:Rails ActiveRecord how do I find all records where the record is not joined with a particular other record?Rails ActiveRecord 如何查找未与特定其他记录连接的所有记录?
【发布时间】:2015-06-07 11:04:00
【问题描述】:

我想搜索不属于第 1 组 (Groups) 的所有用户 (Users),并由 UserGroups 加入,即“查找所有没有将用户组记录绑定到组的用户1."

我可以使用User.all 查找所有用户或使用User.where('name like ?' , '%'+params[:search]+'%') 按名称查找他们

我什至可以找到那些没有会员资格的人:

User.includes(:user_groups).where( :user_groups => { :user_id => nil } )

但是我怎么说,“找到所有不是第 1 组成员的 Users?”

更新:这里是有效的 SQL:

select * from Users as u where not exists (select 1 from UserGroups where group_id = 1 and user_id = u.id);

或者,如果您更喜欢缓存的NOT IN

select * from Users as u where u.id not in (select user_id from UserGroups where group_id = 1);

更新:

我现在发现的唯一方法是原始 SQL,但我会喜欢真正的 ActiveRecord 方法:

User.where('name like ? and id not in (select user_id from UserGroups where group_id = ?)' , '%'+params[:search]+'%',@group.id)

【问题讨论】:

  • 试试这个 -- User.includes(:user_groups).where( "user_groups.user_id != users.id AND group_id = ? ",@group.id ).where("name LIKE ?", '%'+params[:search]+'%' ).references(:user_groups)
  • 嗯@R_O_R,不同。而不是不在,使用连接。
  • @deith,你得到了想要的结果?
  • 是的,确实如此,@R_O_R,但我正在尝试使用 ActiveRecord。看看 D-Side 的回答,太棒了。
  • 好的..我没有测试我给出的代码,这就是为什么我也确认你的逻辑是否虚假.. :p 谢谢你试一试..

标签: ruby-on-rails activerecord


【解决方案1】:

这个:

select user_id from UserGroups where group_id = 1;

...本质上是:

@group.user_groups.select(:user_id)
  • 类似的方法存在于has_many 关联中。似乎是为了构建子查询。

所以这个:

select * from Users as u
where u.id not in (select user_id from UserGroups where group_id = 1);

这是:

User.where.not(id: @group.user_groups.select(:user_id))
  • 条件中的值是Relation,因此它作为子查询嵌入。

还有这个:

select * from Users as u
where not exists
  (
    select 1 from UserGroups
    where group_id = 1 and user_id = u.id
  );

是...唯一棘手的部分是我们必须引用外部表的值,这在查询中不是常量。所以我们必须以另一种方式引用表的字段。一点 Arel 就可以了:

users = User.arel_table # `arel_table` is a sign of some serious SQL business
User.where(@group.user_groups.where(user_id: users[:id]).exists.not)

您可能还想查看one of my other recent answers about NOT EXTSTS

您也可以从“多次通过”中使用ids,但我不知道它是否会从连接模型而不是连接模型中获取它们。

【讨论】:

  • 当,@D-side,这很酷。它几乎有效。问题是@group.user_group_ids 等价于select id from UserGroups where group_id = 1not select user_id from ....。 (不同的是它是从连接表中选择id 而不是user_id)。如果我能做到这一点,我会喜欢的。
  • 我很喜欢NOT IN 而不是NOT EXISTS,因为它允许缓存,正如许多人指出的那样。
  • 嗯,不完全是,它返回所有用户...我会在几分钟内检查 SQL
  • 等一下,NOT EXISTS 的案例就是这样做的。我现在正在尝试NOT IN...
  • 太棒了,你太棒了!我不知道NOT EXISTS,但NOT IN 效果惊人!脱帽致敬!
【解决方案2】:

在 where 子句中尝试像这样使用“字段不在列表中”。

User.includes(:user_groups).where('user_id not in (?)', :group_1_id)

在您的情况下,将 group_1_id 替换为第 1 组的标识符。 我是从这个question 得到的。

虽然我没有测试它。所以你可以试试具体的语法。

【讨论】:

  • 但这不会过滤掉所有拥有会员资格的所有用户吗?我想只列出那些没有第 1 组成员资格的人。如果用户有第 2 组成员资格,我想列出他们。
  • 不确定你的情况是什么 :user_groups 。也许将其替换为您要排除的组的特定 ID。
  • 哦,我明白了,您使用的是not in,但这不完整吗?我会试试的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-03
  • 1970-01-01
  • 2016-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多