SQL:WHERE Joined Set 必須包含所有值,但可能包含更多
在SQL 中,「WHERE JOINED SET」子句確保連接表在其結果集中包含特定值。但是,連接表也可能包含不屬於條件的附加價值。這個概念在實務上實施起來可能具有挑戰性,特別是在確定條件中包含哪些值時。
考慮以下範例:
場景:
你有三個表:offer、sports 和Offers_sports,分別代表Offers、sports 以及它們之間的關係。您想要選擇包含給定運動名稱陣列的優惠。優惠必須包含所有運動項目,但也可能包括其他運動項目。
資料:
offers | id | name | | --- | ---- | | 1 | light | | 2 | medium | | 3 | all | | 4 | extreme | sports | id | name | | --- | ---- | | 1 | Yoga | | 2 | Bodyboarding | | 3 | Surfing | | 4 | Parasailing | | 5 | Skydiving | offers_sports | offer_id | sport_id | | --- | ---- | | 1 | 1 | | 1 | 2 | | 2 | 1 | | 2 | 2 | | 2 | 3 | | 3 | 1 | | 3 | 2 | | 3 | 3 | | 3 | 4 | | 3 | 5 | | 4 | 3 | | 4 | 4 | | 4 | 5 |
期望結果:
給定數組["Bodyboarding", "Surfing"] ,查詢應返回優惠媒介以及所有這些,因為它們包含兩種指定的運動。優惠燈不應退回,因為它不包含這兩種運動。
不正確的查詢:
以下查詢,按運動名稱分組並確保恰好有兩個每項優惠均包含體育運動,不退貨結果:
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而不是運動名稱進行分組,並使用COUNT( 檢查每個優惠中包含的不同運動的數量DISTINCT):
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(DISTINCT sports.name) = ?", sport_names.size) end end
以上是如何在 SQL 中選擇包含所有給定體育項目(但可能更多)的報價?的詳細內容。更多資訊請關注PHP中文網其他相關文章!