条件为连接中的所有记录都为true

时间:2013-03-15 11:19:44

标签: ruby-on-rails activerecord arel

我正在尝试从A返回记录,其中B的所有匹配记录都满足条件。目前,我的查询从A返回记录,其中有来自B的任何满足条件的记录。让我把它放到现实世界的场景中。

Post.joins(:categories)
    .where(:categories => { :type => "foo" })

这将返回Post个类型为“foo”的类别,我想要的是Post,其类别为“foo”类型!

帮助表示赞赏!

3 个答案:

答案 0 :(得分:2)

使用在IRC上的#rubyonrails中发布的db / schema.rb,例如:

Incident.select("incidents.id").
joins("INNER JOIN category_incidents ON category_incidents.incident_id = incidents.id").
joins("INNER JOIN category_marks ON category_marks.category_id = category_incidents.category_id").
where(:category_marks => { :user_group_id => current_user.user_group_id }).
group("incidents.id").
having("SUM(CASE WHEN category_marks.inc = 1 THEN 1 ELSE 0 END) = count(category_indicents.incident_id)")

会做到这一点。

它连接current_user的category_marks,并检查.inc = 1的记录数是否等于所有连接记录的数量。

请注意,这只会触发incident.id

答案 1 :(得分:1)

我会在此查询的末尾添加一个select来检查所有类别是否都有类型foo。我还会通过向Category模型添加实例方法来简化该检查。

Post.joins(:categories).select{|p| p.categories.all?(&:type_foo?)}

类别模型

 def type_foo?
   type == "foo"
 end

附加:这有点“hacky”,但你可以通过这种方式将其作为范围。

class Post < ActiveRecord::Base
  scope :category_type_foo, lambda{ 
    post_ids = Post.all.collect{|p| p.id if p.categories.all?(&:type_foo?).compact
    Post.where(id: post_ids) }
end

答案 2 :(得分:0)

您是否尝试过相反的查询?即。

Categories.where(type: 'foo').joins(:posts)

我可能误解了你的问题。

另一种选择是

Post.joins(:classifications).where(type: 'foo')