Nhóm theo offer.id
, không phải bởi sports.name
(hoặc 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;
Giả sử cách triển khai điển hình:
-
offer.id
vàsports.id
được định nghĩa là khóa chính. -
sports.name
được xác định là duy nhất. -
(sport_id, offer_id)
trongoffers_sports
được xác định là duy nhất (hoặc PK).
Bạn không cần DISTINCT
trong số đếm. Và count(*)
thậm chí còn rẻ hơn một chút.
Câu trả lời liên quan với kho các kỹ thuật khả thi:
- Cách lọc kết quả SQL theo quan hệ có nhiều lần
Được thêm bởi @max (OP) - đây là truy vấn ở trên được đưa vào 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