Country
has_many residences
和Residence
has_many listed_amenities
与amenities
相关联。我需要知道位于residences
且ID为1 Country
amenities
的{{1}}有{{4,49,50} {他们可以拥有更多,但他们有拥有所有这三个)。
以下Ruby on Rails(v4.2.4)代码可以解决这个问题:
id_list = [48, 49, 50]
Country.first.
residences.
where(id: Residence.
joins(:listed_amenities).
where(listed_amenities: {amenity_id: id_list}).
group('residences.id').
having("count(listed_amenities.*) = ?", id_list.size).
pluck(:id)).
count
它产生以下SQL:
SELECT "countries".*
FROM "countries"
ORDER BY "countries"."id" ASC LIMIT 1
SELECT "residences"."id"
FROM "residences"
INNER JOIN "listed_amenities"
ON "listed_amenities"."residence_id" = "residences"."id"
WHERE "listed_amenities"."amenity_id" IN (48, 49, 50)
GROUP BY residences.id
HAVING count(listed_amenities.*) = 3
SELECT COUNT(*)
FROM "residences"
WHERE "residences"."country_id" = $1
AND "residences"."id"
IN (51, 59, 60, ...) [["country_id", 1]]
显然,这是一种解决特定问题的昂贵方法,每个表都有超过1,000,000个条目。
如何以更好/更快的方式在PostgreSQL(9.4.4)上解决这个问题?是否有一条神奇的SQL行可以解决这个问题?
感谢“Get the count of rows count after GROUP BY”我有以下SQL查询来搜索所有residences
,但我缺乏将Country
连接到它的SQL专有技术:
SELECT count(*) AS ct
FROM (
SELECT 1
FROM listed_amenities
WHERE amenity_id IN (48, 49, 50)
GROUP BY residence_id
HAVING count(*) = 3
) sub;
rails g scaffold Country name
rails g scaffold Residence country:references name:string
rails g scaffold Amenity name:string
rails g scaffold ListedAmenity residence:references amenity:references
应用/模型/ country.rb
class Country < ActiveRecord::Base
has_many :residences
end
应用/模型/ residences.rb
class Residence < ActiveRecord::Base
belongs_to :country
has_many :listed_amenities
has_many :amenities, through: :listed_amenities
end
应用/模型/ amenities.rb
class Residence < ActiveRecord::Base
belongs_to :country
has_many :listed_amenities
has_many :amenities, through: :listed_amenities
end
应用/模型/ listed_amenities.rb
class ListedAmenity < ActiveRecord::Base
belongs_to :residence
belongs_to :amenity
end
答案 0 :(得分:1)
我认为你可以将其简化为:
Residence.
joins(:listed_amenities, :country).
where(listed_amenities: {amenity_id: id_list}).
where(countries: {id: 1}).
group('residences.id').
having("count(listed_amenities.*) = ?", id_list.size)
对于计数,请尝试添加:
count.count