Rails / SQL: найдите родителей, которые не имеют детей или имеют всех детей с условием - PullRequest
0 голосов
/ 04 марта 2019

Мне нужно найти родителей, которые либо не имеют детей, либо имеют всех детей исключительно с состоянием (статус = 1).

class Parent
  has_many :children
end

class Child
  enum status: [ :confirmed, :not_confirmed ]
  belongs_to :parent
end

Я знаю первую часть, которая посвящена поиску родителей без детей.

Parent.joins(:children).where('count(children) = 0')

Ответ Rails.

Ответы [ 2 ]

0 голосов
/ 05 марта 2019

Поскольку вы используете Postgres, вы можете использовать запрос NOT EXISTS:

# Parents with no children
Parent.where.not('exists (?)', Child.where('children.parent_id = parents.id').select(1))

Этот запрос работает лучше, чем любой, требующий объединения, так как EXPLAIN покажет вам, что Postgres выполнитэто с Nested Loop Anti Join операцией.

0 голосов
/ 05 марта 2019

Вот решение в Rails:

grp = Parent.left_outer_joins(:children).distinct
models = grp.where('children.id IS NULL').or(grp.where('children.status = 1'))

В основном вам нужно использовать LEFT OUTER JOIN (см. left_outer_joins в Rails5 Reference ).

Iне думайте, что ваш пример первой части работает.Было бы возвращено сообщение об ошибке типа

# ActiveRecord::StatementInvalid (PG::GroupingError: ERROR:  
# aggregate functions are not allowed in WHERE

, а также Rails joins is INNER JOIN.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...