Gruppér efter offer.id , ikke efter sports.name (eller sports.id ):
SELECT o.*
FROM sports s
JOIN offers_sports os ON os.sport_id = s.id
JOIN offers o ON os.offer_id = o.id
WHERE s.name IN ('Bodyboarding', 'Surfing')
GROUP BY o.id -- !!
HAVING count(*) = 2;
Forudsat den typiske implementering:
offer.idogsports.ider defineret som primær nøgle.sports.nameer defineret unikt.(sport_id, offer_id)ioffers_sportser defineret unik (eller PK).
Du behøver ikke DISTINCT i optællingen. Og count(*) er endnu en smule billigere.
Relateret svar med et arsenal af mulige teknikker:
- Sådan filtreres SQL-resultater i en har-mange-gennem-relation
Tilføjet af @max (OP) - dette er ovenstående forespørgsel rullet ind i ActiveRecord:
class Offer < ActiveRecord::Base
has_and_belongs_to_many :sports
def self.includes_sports(*sport_names)
joins(:sports)
.where(sports: { name: sport_names })
.group('offers.id')
.having("count(*) = ?", sport_names.size)
end
end