我如何找出1个模型的多少条记录具有关联的关联对象?

时间:2019-05-28 08:05:54

标签: ruby ruby-on-rails-3 activerecord associations active-record-query

我有两个模型-PropertyPhotos

class Property < ActiveRecord::Base
  has_many :photos, dependent: :destroy
end

class Photo < ActiveRecord::Base
  belongs_to :property
end

我要做的就是创建一个范围,该范围仅返回实际具有照片的属性(即photos.count > 0)。

我已经尝试了一百万次查询迭代,但是由于某种原因它们无法正常工作。

查看一些我尝试过的例子和结果:

[32] pry(main)> Property.includes(:photos).where('photos.count > 0').count
   (4.1ms)  SELECT COUNT(DISTINCT "properties"."id") FROM "properties" LEFT OUTER JOIN "photos" ON "photos"."property_id" = "properties"."id" WHERE (photos.count > 0)
ActiveRecord::StatementInvalid: PG::GroupingError: ERROR:  aggregate functions are not allowed in WHERE
LINE 1: ..."photos"."property_id" = "properties"."id" WHERE (photos.cou...
                                                             ^
[33] pry(main)> Property.joins(:photos).where('photos.count > 0').count
   (11.1ms)  SELECT COUNT(*) FROM "properties" INNER JOIN "photos" ON "photos"."property_id" = "properties"."id" WHERE (photos.count > 0)
ActiveRecord::StatementInvalid: PG::GroupingError: ERROR:  aggregate functions are not allowed in WHERE
LINE 1: ..."photos"."property_id" = "properties"."id" WHERE (photos.cou...
                                                             ^

[38] pry(main)> Property.joins(:photos).count("properties.id").count
   (158.2ms)  SELECT COUNT(properties.id) FROM "properties" INNER JOIN "photos" ON "photos"."property_id" = "properties"."id"
NoMethodError: undefined method `count' for 72604:Fixnum
from (pry):38:in `__pry__'

[39] pry(main)> Property.joins(:photos).count("properties.id")
   (50.6ms)  SELECT COUNT(properties.id) FROM "properties" INNER JOIN "photos" ON "photos"."property_id" = "properties"."id"
=> 72604

[40] pry(main)> Photo.joins(:properties).count("photos.id")
ActiveRecord::ConfigurationError: Association named 'properties' was not found on Photo; perhaps you misspelled it?
from /.rvm/gems/ruby-2.3.7@myapp/gems/activerecord-3.2.22.5/lib/active_record/associations/join_dependency.rb:112:in `build'

[41] pry(main)> Photo.joins(:property).count("photos.id")
   (65.0ms)  SELECT COUNT(photos.id) FROM "photos" INNER JOIN "properties" ON "properties"."id" = "photos"."property_id"
=> 72604

[42] pry(main)> Photo.joins(:property).count("photos.id")
   (60.5ms)  SELECT COUNT(photos.id) FROM "photos" INNER JOIN "properties" ON "properties"."id" = "photos"."property_id"
=> 72604

[43] pry(main)> Property.joins(:photos).count("properties.id").distinct
   (46.4ms)  SELECT COUNT(properties.id) FROM "properties" INNER JOIN "photos" ON "photos"."property_id" = "properties"."id"
NoMethodError: undefined method `distinct' for 72604:Fixnum
from (pry):43:in `__pry__'

[44] pry(main)> Property.joins(:photos).distinct.count("properties.id")
=> 0

这应该很简单,但是由于某些原因,它比我预期的要困难得多。

有想法吗?

3 个答案:

答案 0 :(得分:0)

Rails-5 中,您可以使用 left_outer_joins

Property.left_outer_joins(:photos).where(photos: {id: nil})

生成的SQL将

SELECT properties.*
FROM properties 
LEFT OUTER JOIN photos 
ON photos.property_id = property.id
WHERE photos.id IS NULL

Rails-3 中,您可以尝试关注

Property.joins("LEFT OUTER JOIN photos ON properties.id = photos.property_id").where(photos: {id: nil})

答案 1 :(得分:0)

使用Property.joins(:photos)(执行内部联接)将返回包含相关照片的属性。含义是带有property_id的照片。尽管使用left_outer_joinsLEFT JOINLEFT OUTER JOIN的答案会起作用,但使用.where(photos: { id: nil })会错误地使用左联接。在“属性”和“图片”之间使用INNER JOINJOINjoins可以得到我在此答案开始时所说的内容。左联接将返回所有属性,带或不带相关照片。

enter image description here

答案 2 :(得分:0)

为了仅获取实际上具有Properties(即photos)的photos.count > 0,您需要对两个表执行inner join

在Rails 5中,您可以通过以下命令进行操作

Property.joins(:photos)

这将转换为SQL

SELECT  "properties".* FROM "properties" INNER JOIN "photos" ON "photos"."property_id" = "properties"."id"

如果要在查询中添加更多条件,可以添加Where子句

Property.joins(:photos).where(properties: {id: [1, 2]})