如何选择子项不存在的记录

时间:2010-09-21 04:22:10

标签: ruby-on-rails activerecord

在rails中我有2个表:

bans(ban_id, admin_id)
ban_reasons(ban_reason_id, ban_id, reason_id)

我想查找某个管理员的所有bans,其中ban_reasons表中没有记录。如何在Rails中执行此操作而不循环遍历所有禁止记录,并使用ban.ban_reasons.nil?过滤掉所有使用单个SQL语句(希望)执行此操作的文件。

我只需要这样做:(但我想以“rails”的方式去做)

SELECT bans.* FROM bans WHERE admin_id=1234 AND 
                              ban_id NOT IN (SELECT ban_id FROM ban_reasons)

3 个答案:

答案 0 :(得分:2)

ActiveRecord只能让你到达一定程度,所有事情都应该由原始SQL完成。 AR的优点在于它可以很容易地做到这一点。

但是,自从Rails 3以来,您可以使用AREL API执行几乎所有操作,尽管原始SQL可能看起来或者看起来不那么可读。

我会使用原始SQL,如果你的表现不好,可以尝试另一个查询:

SELECT       b.* 
FROM         bans b
LEFT JOIN    ban_reason br on b.ban_id = br.ban_id
WHERE        br.ban_reason_id IS NULL

答案 1 :(得分:2)

您的解决方案效果很好(只有一个请求),但它几乎是简单的SQL:

bans = Ban.where("bans.id NOT IN (SELECT ban_id from ban_reason)")

您也可以尝试以下操作,并让rails完成部分工作:

bans = Ban.where("bans.id NOT IN (?)", BanReason.select(:ban_id).map(&:ban_id).uniq)

答案 2 :(得分:0)

使用Where Exists gem(我是其作者):

Ban.where(admin_id: 123).where_not_exists(:ban_reasons)