Agrupar por
offer.id
, não por 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;
Assumindo a implementação típica:
offer.id
esports.id
são definidos como chave primária.sports.name
é definido como único.(sport_id, offer_id)
emoffers_sports
é definido como único (ou PK).
Você não precisa de
DISTINCT
na contagem. E count(*)
é ainda um pouco mais barato, ainda. Resposta relacionada com um arsenal de técnicas possíveis:
- Como filtrar resultados de SQL em uma relação de muitos
Adicionado por @max (o OP) - esta é a consulta acima inserida no 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