Rails查找与零has_manylogging关联的logging
这似乎相当简单,但我不能让它在Google上出现。
如果我有:
class City < ActiveRecord::Base has_many :photos end class Photo < ActiveRecord::Base belongs_to :city end
我想find所有没有照片的城市。 我很乐意能够打电话给…
City.where( photos.empty? )
…但不存在 那么,你如何做这种查询?
更新:现在已经find了原始问题的答案,我很好奇,你如何构造反向?
IE:如果我想创build这些作为示波器:
scope :without_photos, includes(:photos).where( :photos => {:city_id=>nil} ) scope :with_photos, ???
嗯,在这里find它: https : //stackoverflow.com/a/5570221/417872
City.includes(:photos).where(photos: { city_id: nil })
当试图从连接表中查找没有匹配logging的logging时,您需要使用LEFT OUTER JOIN
scope :with_photos, joins('LEFT OUTER JOIN photos ON cities.id = photos.city_id').group('cities.id').having('count(photos.id) > 0') scope :without_photos, joins('LEFT OUTER JOIN photos ON cities.id = photos.city_id').group('cities.id').having('count(photos.id) = 0')
在Rails 5中 ,要查找所有没有照片的城市,可以使用left_outer_joins
:
City.left_outer_joins(:photos).where(photos: {id: nil})
这将导致SQL如下所示:
SELECT cities.* FROM cities LEFT OUTER JOIN photos ON photos.city_id = city.id WHERE photos.id IS NULL
使用includes
:
City.includes(:photos).where(photos: {id: nil})
将会有相同的结果,但会导致很多丑陋的SQL,如:
SELECT cities.id AS t0_r0, cities.attr1 AS t0_r1, cities.attr2 AS t0_r2, cities.created_at AS t0_r3, cities.updated_at AS t0_r4, photos.id AS t1_r0, photos.city_id AS t1_r1, photos.attr1 AS t1_r2, photos.attr2 AS t1_r3, photos.created_at AS t1_r4, photos.updated_at AS t1_r5 FROM cities LEFT OUTER JOIN photos ON photos.city_id = cities.id WHERE photos.id IS NULL
我用一个join来获得所有的照片:
scope :with_photos, -> { joins(:photos).distinct }
更容易写和理解,特殊情况下。 不过,我不确定做一个连接和一个包含的效率是多less