Найти только записи, которые имеют все удаленные ассоциации

Обновить

November 2018

Просмотры

120 раз

-1

Вопрос идет как RoR, но я предполагаю, что этот вопрос относится больше на уровне запросов.

У меня есть модель

ModelA has_many ModelB

и я использую paranoidкамень в обоих из них.

Я пытаюсь выяснить все , ModelAкоторые не имеют либо не ModelBсвязанных с ними или все его ModelBбыли удалены (поэтому deleted_atне NULL).

На основании этого вопроса , я был в состоянии достичь желаемого результата, но чтение запроса не имеет большого смысла для меня , как это работает.

ModelA.joins('LEFT OUTER JOIN model_bs ON model_bs.model_a_id = model_as.id AND model_bs.deleted_at IS NULL')
  .where('model_bs.model_a_id IS NULL')
  .group(model_as.id)

Как уже упоминалось, чтение этого запроса не имеет смысла для меня, потому что присоединяется к условию, я использую также быть утратившим на ИНЕКЕ впоследствии.

Может кто-то пожалуйста, помогите мне получать запрос правильно установить и, если это правильный путь, объясни мне, как делает разбивку запроса в правильный результат.

Обновить:

Как уже упоминалось в комментарии ниже, после того, как какой-то сырой SQL мне удалось понять, что происходит. Кроме того, написали мое AR решения, чтобы сделать его более ясным (по крайней мере, с моей точки зрения)

Преодолевая его вниз:

Этот запрос представляет собой регулярное левое внешнее соединение, которое возвращает все модели на левый самостоятельно, если есть ассоциация по праву.

ModelA.joins('LEFT OUTER JOIN model_bs ON model_bs.model_a_id = model_as.id')

Добавление дополнительного условия в соединении

AND model_bs.deleted_at IS NULL

будет возвращать строки с ModelBатрибутами доступных , если есть один , связанный, в противном случае будет возвращать одну строку с только ModelA.

Применяя над этими строками , .where('model_bs.model_a_id IS NULL')будет держать только те строки , которые не имеют никаких связанные моделей.

Примечание: В этом случае, используя атрибут model_a_idили любой другой атрибут model_bбудет работать, но если идти по этому пути, я бы рекомендовал использовать атрибут, если связь существует, его всегда будет там. В противном случае вы могли бы в конечном итоге с неправильным результатам.

И, наконец, AR, что я в конечном итоге с помощью того, чтобы перевести то, что я хотел:

ModelA.joins('LEFT OUTER JOIN model_bs ON model_bs.model_a_id = model_as.id AND model_bs.deleted_at IS NULL')
  .group('model_as.id')
  .having('count(model_bs.id) = 0')

1 ответы

0

Эй , вы можете попробовать этот путь я испытал его в mysqlвы можете проверить егоPG

ModelA.joins('LEFT OUTER JOIN model_bs ON model_bs.model_a_id = model_as.id')
  .group('model_as.id')
  .having('SUM(CASE WHEN model_bs.deleted_at IS NULL THEN 0 ELSE 1 END) AS OCT = 0')

Связанные вопросы