Gruppera efter offer.id
, inte av 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;
Förutsatt den typiska implementeringen:
offer.id
ochsports.id
definieras som primärnyckel.sports.name
definieras unikt.(sport_id, offer_id)
ioffers_sports
är definierad unik (eller PK).
Du behöver inte DISTINCT
i räkningen. Och count(*)
är ännu lite billigare.
Relaterat svar med en arsenal av möjliga tekniker:
- Hur man filtrerar SQL-resultat i en har-många-genom-relation
Tillagt av @max (OP) - det här är frågan ovan som rullats in 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