我希望有一个简单的解决方案,不涉及find_by_sql,如果没有,那么我想这将不得不工作。

我发现这篇文章引用了这个:

Topic.find(:all, :conditions => { :forum_id => @forums.map(&:id) })

哪个是一样的

SELECT * FROM topics WHERE forum_id IN (<@forum ids>)

我想知道是否有一种方法可以不这样做,比如:

SELECT * FROM topics WHERE forum_id NOT IN (<@forum ids>)

当前回答

这种方法优化了可读性,但在数据库查询方面效率不高:

# Retrieve all topics, then use array subtraction to
# find the ones not in our list
Topic.all - @forums.map(&:id)

其他回答

借助jonnii:

Topic.find(:all, :conditions => ['forum_id not in (?)', @forums.pluck(:id)])

使用提取而不是在元素上进行映射

通过railsconf 2012找到你不知道rails可以做的10件事

这些论坛id能够以一种实用的方式计算出来吗?例如,你能以某种方式找到这些论坛吗?如果是这样的话,你应该做一些事情

Topic.all(:joins => "left join forums on (forums.id = topics.forum_id and some_condition)", :conditions => "forums.id is null")

哪一个会比做一个SQL不在更有效

最初的帖子特别提到了使用数字id,但我来这里寻找用字符串数组做NOT IN的语法。

ActiveRecord也会很好地为你处理:

Thing.where(['state NOT IN (?)', %w{state1 state2}])

当你查询一个空数组时,在where块中添加"<< 0"到数组中,这样它就不会返回"NULL"并中断查询。

Topic.where('id not in (?)',actions << 0)

If actions可以是空数组或空数组。

你可以在你的条件下使用sql:

Topic.find(:all, :conditions => [ "forum_id NOT IN (?)", @forums.map(&:id)])