Raggruppa per offer.id
, non da sports.name
(o 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;
Assumendo l'implementazione tipica:
offer.id
esports.id
sono definiti come chiave primaria.sports.name
è definito unico.(sport_id, offer_id)
inoffers_sports
è definito unico (o PK).
Non hai bisogno di DISTINCT
nel conteggio. E count(*)
è ancora un po' più economico.
Risposta correlata con un arsenale di possibili tecniche:
- Come filtrare i risultati SQL in una relazione ha molti-attraverso
Aggiunto da @max (l'OP):questa è la query precedente inserita in 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