Gruppieren Sie nach offer.id
, nicht nach sports.name
(oder 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;
Angenommen die typische Implementierung:
offer.id
undsports.id
sind als Primärschlüssel definiert.sports.name
ist eindeutig definiert.(sport_id, offer_id)
inoffers_sports
ist eindeutig definiert (oder PK).
Sie brauchen DISTINCT
nicht in der Zählung. Und count(*)
ist sogar noch etwas billiger.
Verwandte Antwort mit einem Arsenal möglicher Techniken:
- So filtern Sie SQL-Ergebnisse in einer Has-Viele-Durch-Beziehung
Hinzugefügt von @max (dem OP) – dies ist die obige Abfrage, die in ActiveRecord gerollt wird:
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