Выберите объекты, где у всех детей нет внуков

У меня есть следующая трехуровневая иерархия моделей:

class Parent < AR::Base
  has_many :children
end

class Child < AR::Base
  has_many :grandchildren
  belongs_to :parent

  attr_accessible :my_number
end

class Grandchild < AR::Base
  belongs_to :child
end

Ожидается, что все Parentс будет иметь несколько childrenно каждый Child может или не может иметь какие-либо grandchildren,

Я хочу получить все Parent объекты, для которых все children не иметь grandchildren, Как я могу это сделать? Я бы предпочел Rails-way, и у меня есть Squeel; но я согласен на сырой SQL.

Бонусные баллы, если вы можете дать мне все Parent объекты, для которых все children не иметь grandchildren и все children иметь my_number < 5,

1 ответ

Решение

После небольшого исследования я думаю, что я получил решение с помощью group а также having статьи.

Вы можете добавить эту область к вашему Parent модель. Обратите внимание, что нам нужно вручную определить joins для того, чтобы использовать LEFT JOIN вместо по умолчанию INNER JOIN Rails генерирует. Более подробная информация о SQL JOINS здесь.

class Parent < AR::Base
  scope :with_children_having_no_grand_children, -> { 
    joins("LEFT JOIN `children` ON `children`.`parent_id` = `parents`.`id` 
           LEFT JOIN `grand_children` ON `grand_children`.`child_id` = `children`.`id`")
    .group('parents.id')
    .having('COUNT(grand_children.id) = 0 AND COUNT(children.id) > 0')
  }
end

И тогда вы можете использовать:

Parent.with_children_having_no_grand_children

По второму вопросу, предполагая :my_number атрибут хранится в БД, вы можете сделать:

Parent.with_children_having_no_grand_children.where(children: { my_number: 5 }))
Другие вопросы по тегам