データベースには、オファー、 sports、結合テーブル Offers_sports.指定されたすべてのスポーツが存在する必要があるという条件で、指定された一連のスポーツを含むオファーを取得したいと考えていますが、追加のスポーツも含まれる可能性があります。
たとえば、次のオファーを考慮します:
「ボディボード」と「サーフィン」を含むオファーをクエリすると、「中」と「すべて」の両方が返されると予想されますが、「ライト」は返されません。ただし、現在のクエリ:
Offer.joins(:sports) .where(sports: { name: ["Bodyboarding", "Surfing"] }) .group("sports.name") .having("COUNT(distinct sports.name) = 2")
および同等の SQL:
SELECT "offers".* FROM "offers" INNER JOIN "offers_sports" ON "offers_sports"."offer_id" = "offers"."id" INNER JOIN "sports" ON "sports"."id" = "offers_sports"."sport_id" WHERE "sports"."name" IN ('Bodyboarding', 'Surfing') GROUP BY sports.name HAVING COUNT(distinct sports.name) = 2;
結果が返されません。
これを修正するには、グループ化するようにクエリを変更します。スポーツ名の代わりにオファー 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;
または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
この変更により、結果を適切にグループ化し、必要なフィルタリング基準を適用して、指定されたスポーツを含む希望のオファーを取得できるようになります。
以上が多対多の関係で特定のスポーツのセットを含むオファーをクエリするにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。