Как выбрать записи, где ребенка не существует - PullRequest
4 голосов
/ 21 сентября 2010

В рельсах у меня есть 2 таблицы:

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

Я хочу найти все bans для определенного администратора, для которого нет записи в таблице ban_reasons. Как я могу сделать это в Rails, не просматривая все записи банов и не отфильтровывая все с помощью ban.ban_reasons.nil? Я хочу сделать это (надеюсь) с помощью одного оператора SQL.

Мне просто нужно сделать: (Но я хочу сделать это "рельсовым" способом)

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

Ответы [ 3 ]

2 голосов
/ 21 сентября 2010

Ваше решение прекрасно работает (только один запрос), но это почти простой 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 голосов
/ 21 сентября 2010

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
0 голосов
/ 03 сентября 2015

Использование Там, где существует драгоценный камень (автором которого я являюсь):

Ban.where(admin_id: 123).where_not_exists(:ban_reasons)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...