你滥用includes
. 这是为了急切加载,而不是为了加入!
但你的方法是对的。它可以用于您的情况。NOT IN (?)
但是即使合乎逻辑,Rails 也不会发出嵌套请求。您将获得 2 个查询(您将获得NOT IN (id1, id2....,)
而不是NOT IN (SELECT ....)
)。
所以我建议你使用squeel gem:
常规 AR 代码(也可以用 squeel 美化):
featured_posts = WpPost.joins(:terms).where(terms:{term: ['featured']}).uniq
然后使用 sqeel 的力量:
WpPost.where{id.not_in featured_posts}
(in
并且not_in
也被称为>>
and<<
但我不想吓到任何人)
注意使用块和符号的缺失。
SQLite 下
基于
Chinook 数据库的一些测量:
> Track.all
Track Load (35.0ms) SELECT "Track".* FROM "Track"
与joins
和的关系like
:
oldie = Track.joins{playlists}.where{playlists.name.like_any %w[%classic% %90%]}
这是NOT IN
:
> Track.where{trackId.not_in oldie}.all
Track Load (37.5ms) SELECT "Track".* FROM "Track" WHERE "Track"."trackId"
NOT IN (SELECT "Track"."TrackId" FROM "Track" INNER JOIN "PlaylistTrack" ON
"PlaylistTrack"."TrackId" = "Track"."TrackId" INNER JOIN "Playlist" ON
"Playlist"."PlaylistId" = "PlaylistTrack"."PlaylistId"
WHERE (("Playlist"."name" LIKE '%classic%' OR "Playlist"."name" LIKE '%90%')))
供参考:
Track.where{trackId.not_in oldie}.count # => 1971
Track.count # => 3503
# join table:
PlaylistTrack.count # => 8715
结论:我没有看到由NOT IN
. 35.0 与 37.5 没有明显区别。几次 35.0 变成了 37.5,反之亦然。