2016-08-01 39 views
0

有两个表:用户和教师。 Teacher.user_id来自用户。那么,如何在单个查询中找到所有不在教师中的用户。其他表中未引用的回溯记录,ActiveRecord查询

我的意思是沿着线的东西:

  User.not_in(Teacher.all) 
+1

你确定你不是指“数据库表”而不是“数据库”吗? –

+0

糟糕。我正是这个意思。我是一名铁杆新手。所以,我可以互换使用它 –

回答

0

您可以使用where.not查询从ActiveRecord尝试类似如下:

User.where.not(id: Teacher.pluck(:user_id).reject {|x| x.nil?}) 

注:使用reject方法,以防在某些记录中有零值。

+1

因此完美无瑕。非常感谢。 –

+0

很高兴它的工作,但我也建议考虑其他答案http://stackoverflow.com/a/38706214/2545197以及。 – Abhinay

+1

看来你认为这是不正确的,虽然在这种情况下,我仍然会考虑我们在我的帖子中讨论过的内容,因为如果教师表变得太大,SQL将失败,因为查询只能是这么多字符长,而'Array'可能会导致它超过这个值。简单的解决方法是将pluck版本更改为'Teacher.where.not(id:nil).select(:user_id)',那么它将执行'reject'部分作为子查询。 – engineersmnky

0

我想你应该能够做这样的事

User.where.not(id: Teacher.ids) 
+0

这不会起作用,您应该将'user_id'传递给它而不是'teacher_id' – Abhinay

1

其他用户似乎已经忽略了导轨3标签(因为根据批准的答案删除离开我的回答给后人。):请试试这个

User.where("id NOT IN (?)",Teacher.pluck(:user_id).join(",")) 

这将成为SELECT * FROM users WHERE id NOT IN (....)(两个查询之一从老师那里得到user_id,而另一个得到user(s)不在该列表中)并且可能基于老师表的大小而失败。

其他选项是AREL表:

users = User.arel_table 
User.where(users[:id].not_in(Teacher.select(:user_id).where("user_id IS NOT NULL"))) 

这应该产生类似于

SELECT * FROM users 
WHERE id NOT IN (SELECT user_id FROM teachers WHERE user_id IS NOT NULL) 

(一个查询性能越好)单查询*语法不完全测试

另一个单个查询选项可能是

User.joins("LEFT OUTER JOIN teachers ON teachers.user_id = users.id"). 
    where("teachers.user_id IS NULL") 
+0

嘿,我完全同意你在这里的观点,但不是它仍然运行两个查询? – Abhinay

+0

@Abhinay它不需要SQL返回程序构建一个'Array',然后执行第二个查询,因为'pluck'方法需要这个。相反,整个查询在SQL服务器上执行,只返回所需的结果。但从技术上讲,你可以看到子查询作为第二个查询,因此输入我的第三个建议,这是真正的1查询。 – engineersmnky

+0

明白了,谢谢你的解释。顺便说一句,用户问这个问题的方式,我怀疑他真的意味着rails-3版本。他提到了成为一名新手 – Abhinay

相关问题