从关联模型(表)中查找至少有一个关联的所有记录
Finding all records that has at least one association from associated models (tables)
假设我有这个:
class Tree < ActiveRecord::Base
has_many :fruits
has_many :flowers
end
class Fruit < ActiveRecord::Base
belongs_to :tree
end
class Flower < ActiveRecord::Base
belongs_to :tree
end
如何进行高效查询以获取所有 Tree
实例,这些实例至少有一个 Flower
或 Fruit
实例,或两者都有?这个想法是没有得到根本没有 Flower
和 Fruit
的 Tree
。
获取至少有一个 Flower
或 Fruit
的所有 Tree
的一种非常基本的方法是这样的
flowers = Flower.pluck(:tree_id)
fruits = Tree.pluck(:tree_id)
然后是你想要的Tree
Tree.where(id: [flowers, fruits].flatten)
这会导致对您的数据库进行 3 次查询,这可能是问题,也可能不是问题,具体取决于您的用例。
一种更高级的方法是这样做,它只会产生一个查询。请注意 select
而不是 pluck
的使用,这使得 Rails 最终只发出一个查询成为可能。
flowers = Flower.select(:tree_id)
fruits = Fruit.select(:tree_id)
Tree.where(id: flowers).or(Tree.where(id: fruits))
我会使用这样的查询:
Tree.left_joins(:fruits, :flowers).where('fruits.id IS NOT NULL OR flowers.id IS NOT NULL').distinct
它将产生这个 SQL:
SELECT DISTINCT "trees".* FROM "trees" LEFT OUTER JOIN "fruits" ON "fruits"."tree_id" = "trees"."id" LEFT OUTER JOIN "flowers" ON "flowers"."tree_id" = "trees"."id" WHERE (fruits.id IS NOT NULL OR flowers.id IS NOT NULL)
假设我有这个:
class Tree < ActiveRecord::Base
has_many :fruits
has_many :flowers
end
class Fruit < ActiveRecord::Base
belongs_to :tree
end
class Flower < ActiveRecord::Base
belongs_to :tree
end
如何进行高效查询以获取所有 Tree
实例,这些实例至少有一个 Flower
或 Fruit
实例,或两者都有?这个想法是没有得到根本没有 Flower
和 Fruit
的 Tree
。
获取至少有一个 Flower
或 Fruit
的所有 Tree
的一种非常基本的方法是这样的
flowers = Flower.pluck(:tree_id)
fruits = Tree.pluck(:tree_id)
然后是你想要的Tree
Tree.where(id: [flowers, fruits].flatten)
这会导致对您的数据库进行 3 次查询,这可能是问题,也可能不是问题,具体取决于您的用例。
一种更高级的方法是这样做,它只会产生一个查询。请注意 select
而不是 pluck
的使用,这使得 Rails 最终只发出一个查询成为可能。
flowers = Flower.select(:tree_id)
fruits = Fruit.select(:tree_id)
Tree.where(id: flowers).or(Tree.where(id: fruits))
我会使用这样的查询:
Tree.left_joins(:fruits, :flowers).where('fruits.id IS NOT NULL OR flowers.id IS NOT NULL').distinct
它将产生这个 SQL:
SELECT DISTINCT "trees".* FROM "trees" LEFT OUTER JOIN "fruits" ON "fruits"."tree_id" = "trees"."id" LEFT OUTER JOIN "flowers" ON "flowers"."tree_id" = "trees"."id" WHERE (fruits.id IS NOT NULL OR flowers.id IS NOT NULL)