如何使用 ActiveRecord/Rails 表达 NOT IN 查询?
我希望有一个不涉及 find_by_sql
的简单解决方案,如果没有,那么我想这将必须起作用。
我发现这篇文章引用了以下内容:
Topic.find(:all, :conditions => { :forum_id => @forums.map(&:id) })
这与
SELECT * FROM topics WHERE forum_id IN (<@forum ids>)
我想知道是否有办法做到 NOT IN
是一样的,例如:
SELECT * FROM topics WHERE forum_id NOT IN (<@forum ids>)
I'm hoping there is a easy solution that doesn't involve find_by_sql
, if not then I guess that will have to work.
I found this article which references this:
Topic.find(:all, :conditions => { :forum_id => @forums.map(&:id) })
which is the same as
SELECT * FROM topics WHERE forum_id IN (<@forum ids>)
I am wondering if there is a way to do NOT IN
with that, like:
SELECT * FROM topics WHERE forum_id NOT IN (<@forum ids>)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
Rails 4+:
Rails 3:
其中
actions
是一个数组,其中:[1,2,3,4,5]
Rails 4+:
Rails 3:
Where
actions
is an array with:[1,2,3,4,5]
仅供参考,在 Rails 4 中,您可以使用
not
语法:FYI, In Rails 4, you can use
not
syntax:从rails 4开始:
请注意,最终您不希望forum_ids成为ids列表,而是一个子查询,如果是这样,那么您应该在获取主题之前执行类似的操作:
通过这种方式,您可以在单个查询中获取所有内容:类似于:
另请注意,最终您不想这样做,而是希望加入 - 这可能会更有效。
since rails 4:
Please notice that eventually you do not want the forum_ids to be the ids list, but rather a subquery, if so then you should do something like this before getting the topics:
in this way you get everything in a single query: something like:
Also notice that eventually you do not want to do this, but rather a join - what might be more efficient.
您可以尝试以下操作:
您可能需要执行
@forums.map(&:id).join(',')
。我不记得 Rails 是否会将参数放入 CSV 列表(如果它是可枚举的)。你也可以这样做:
You can try something like:
You might need to do
@forums.map(&:id).join(',')
. I can't remember if Rails will the argument into a CSV list if it is enumerable.You could also do this:
要扩展 @Trung Lê 的答案,在 Rails 4 中您可以执行以下操作:
您还可以更进一步。
如果您需要首先过滤仅发布的主题,然后然后过滤掉您不需要的 id,您可以这样做:
Rails 4 使这一切变得更加容易!
To expand on @Trung Lê answer, in Rails 4 you can do the following:
And you could take it a step further.
If you need to first filter for only published Topics and then filter out the ids you don't want, you could do this:
Rails 4 makes it so much easier!
如果
@forums
为空,则接受的解决方案将失败。为了解决这个问题,我必须这样做,或者,如果使用 Rails 3+:
The accepted solution fails if
@forums
is empty. To workaround this I had to doOr, if using Rails 3+:
上面的大多数答案应该足以满足您的需求,但如果您要做更多这样的谓词和复杂的组合,请查看 Squeel。您将能够执行以下操作:
Most of the answers above should suffice you but if you are doing a lot more of such predicate and complex combinations check out Squeel. You will be able to doing something like:
这些论坛 ID 能否以务实的方式制定出来?例如,您能以某种方式找到这些论坛吗?如果是这种情况,您应该做类似的事情
,这比执行 SQL
not in
更有效Can these forum ids be worked out in a pragmatic way? e.g. can you find these forums somehow - if that is the case you should do something like
Which would be more efficient than doing an SQL
not in
这种方式优化了可读性,但在数据库查询方面效率不高:
This way optimizes for readability, but it's not as efficient in terms of database queries:
您可能想看看 Ernie Miller 的 meta_where 插件。您的 SQL 语句:
...可以这样表达:
Railscasts 的 Ryan Bates 创建了一个 解释 MetaWhere 的精彩截屏视频。
不确定这是否是您正在寻找的,但在我看来,它肯定比嵌入式 SQL 查询更好。
You may want to have a look at the meta_where plugin by Ernie Miller. Your SQL statement:
...could be expressed like this:
Ryan Bates of Railscasts created a nice screencast explaining MetaWhere.
Not sure if this is what you're looking for but to my eyes it certainly looks better than an embedded SQL query.
原来的帖子特别提到了使用数字 ID,但我来这里是为了寻找对字符串数组执行 NOT IN 的语法。
ActiveRecord 也会很好地为你处理这个问题:
The original post specifically mentions using numeric IDs, but I came here looking for the syntax for doing a NOT IN with an array of strings.
ActiveRecord will handle that nicely for you too:
您可以在您的条件中使用 sql:
You can use sql in your conditions:
搭载 jonnii:
元素
使用 pluck 而不是映射通过 railsconf 2012 你不知道 Rails 可以做的 10 件事
Piggybacking off of jonnii:
using pluck rather than mapping over the elements
found via railsconf 2012 10 things you did not know rails could do
当您查询空白数组时,将“<< 0”添加到 where 块中的数组中,这样它就不会返回“NULL”并中断查询。
如果操作可以是空数组或空白数组。
When you query a blank array add "<< 0" to the array in the where block so it doesn't return "NULL" and break the query.
If actions could be an empty or blank array.
这是一个更复杂的“not in”查询,使用 Rails 4 中的子查询使用 squeel。当然,与等效的 sql 相比非常慢,但是嘿,它有效。
该作用域中的前 2 个方法是声明别名 cavtl1 和 tl1 的其他作用域。 <<是 squeel 中的 not in 运算符。
希望这对某人有帮助。
Here is a more complex "not in" query, using a subquery in rails 4 using squeel. Of course very slow compared to the equivalent sql, but hey, it works.
The first 2 methods in the scope are other scopes which declare the aliases cavtl1 and tl1. << is the not in operator in squeel.
Hope this helps someone.
如果有人想使用两个或多个条件,您可以这样做:
If someone want to use two or more conditions, you can do that: