Это в значительной степени синтез обоих других ответов.
Во-первых: придерживаться has_many through
как @ TheChamp предлагает. Возможно, вы уже используете его, просто забыли написать его, иначе он просто не сработает. Ну, вас предупредили.
Как правило, я стараюсь избегать необработанных SQL-запросов в моих запросах. Подсказка о select
, представленная выше, создает рабочее решение, но делает некоторые ненужные вещи, такие как join
, когда нет никакой практической необходимости. Итак, давайте избежим общения. Не в этот раз.
вот причина, почему я предпочитаю has_many through
к has_and_belongs_to_many
во многих ко многим ассоциаций: мы можем запросить сама модель присоединиться без необработанного SQL:
WorkerMembership.select(:worker_id).where(event: @event)
Это не результат, но она заставляет нас список worker_id
s мы не хотим.Тогда мы просто обернуть этот вопрос в «дать мне все, но эти ребята»:
Worker.where.not(id: <...>)
Таким образом, окончательный запрос:
Worker.where.not(id: WorkerMembership.select(:worker_id).where(event: @event))
И выводит один запрос (на @event
с id
равным 1
):
SELECT `workers`.* FROM `workers` WHERE (`workers`.`id` NOT IN (SELECT `worker_memberships`.`worker_id` FROM `worker_memberships` WHERE `worker_memberships`.`event_id` = 1))
Я также отдать должное @apneadiving за его решения и подсказки о mysql2
«s explain
. SQLite's explain
ужасен! Мое решение, если я правильно прочитал результат explain
, так же эффективен, как и @ apneadiving.
@ TheChamp также обеспечил затраты на выполнение всех запросов ответов. Ознакомьтесь с комментариями для сравнения.
интересно! :) – apneadiving
не могли бы вы разделять расходы обоих? просто любопытство – apneadiving
@apneadiving уверенная вещь: http://pastebin.com/BupHkLQf (обязательно переверните перенос текста, таблицы 'explain' длинны) –