如何检查rails中where语句的空关联?

时间:2015-03-23 21:41:15

标签: sql ruby-on-rails where-clause

我有一个名为Category的模型,它可以有许多子类别(也是类别记录)。我想收集数据库中没有子类别的所有类别,例如:

Category.where(subcategories: [])

但是我尝试过的每一个直观[对我]的变化都会引发错误或返回一个空集。它产生了一些我不太了解的SQL:

Category Load (0.5ms) SELECT "categories".* FROM "categories" WHERE 1=0
=> #<ActiveRecord::Relation []> 

有谁能告诉我这样做的正确方法?

编辑:这是定义子类别关系的方式

class Category < ActiveRecord::Base
    has_many :subcategories, class_name: 'Category', foreign_key: 'parent_id'
    belongs_to :parent, class_name: 'Category'
end

3 个答案:

答案 0 :(得分:1)

试试这个:

Category.joins(:subcategories).where(subcategories: {parent_id: nil})

Category.includes(:subcategories).where('subcategories.parent_id IS NULL')

答案 1 :(得分:0)

好的,解决了。我只需要调整Sharvy的建议(我遗忘的一件大事就是添加“连接”)。

以下工作:

Category.includes(:subcategories).where(subcategories: nil)

更新2:好的,这次我真的让它正常工作(非常确定,至少......)。我不得不使用一些丑陋的SQL而不仅仅是一些非常漂亮的ActiveRecord语法,但以下似乎可以做我想要的:

Category.joins("LEFT JOIN categories AS subcategories ON subcategories.parent_id = categories.id").where("subcategories IS NULL")

更新1:抱歉,没关系,这不起作用。正如我在下面评论的那样,我跳过了枪,因为我看到这个查询返回了where(... nil)where.not(... nil)的正确类别计数,但它实际上并没有返回正确的类别。它返回所有没有父类别的类别,而不是所有没有任何子类别的类别。

以下是此查询的一些示例输出:

Category.includes(:subcategories).where(subcategories: nil).last
  Category Load (0.7ms)  SELECT  "categories".* FROM "categories" WHERE "categories"."parent_id" IS NULL  ORDER BY "categories"."id" DESC LIMIT 1
  Category Load (0.5ms)  SELECT "categories".* FROM "categories" WHERE "categories"."parent_id" IN (3158)
 => #<Category id: 3158, name: "A parent", parent_id: nil, created_at: "2015-03-23 19:18:40", updated_at: "2015-03-23 19:18:40", operator_id: nil>

答案 2 :(得分:-1)

怎么样

Category.where("id NOT IN (?)", Subcategory.pluck(:category_id))

这里的问题是您不能直接查询.where子句中的关联。您只能处理实际的列名称。所以我在这里做了一个快速子查询,你可以在其中获取在子类别表中列为关联的类别ID,然后查询不在该列表中的所有类别。