Grouper par offer.id
, pas par sports.name
(ou 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;
En supposant la mise en œuvre typique :
offer.id
etsports.id
sont définis comme clé primaire.sports.name
est défini unique.(sport_id, offer_id)
dansoffers_sports
est défini unique (ou PK).
Vous n'avez pas besoin de DISTINCT
dans le décompte. Et count(*)
est encore un peu moins cher.
Réponse connexe avec un arsenal de techniques possibles :
- Comment filtrer les résultats SQL dans une relation has-many-through
Ajouté par @max (l'OP) - il s'agit de la requête ci-dessus intégrée à 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