SQL: WHERE Set Yang Dicantumkan Mesti Mengandungi Semua Nilai Tetapi Mungkin Mengandungi Lebih Banyak
Dalam SQL, klausa "WHERE JOIND SET" memastikan bahawa jadual bercantum termasuk nilai khusus dalam set hasilnya. Walau bagaimanapun, jadual yang dicantumkan juga mungkin termasuk nilai tambahan yang bukan sebahagian daripada syarat. Konsep ini boleh menjadi mencabar untuk dilaksanakan dalam amalan, terutamanya apabila menentukan nilai yang perlu disertakan dalam keadaan.
Pertimbangkan contoh berikut:
Senario:
Anda mempunyai tiga jadual: tawaran, sukan dan tawaran_sukan, yang mewakili tawaran, sukan dan hubungan antara mereka. Anda ingin memilih tawaran yang termasuk pelbagai nama sukan yang diberikan. Tawaran mesti mengandungi semua sukan tetapi mungkin juga termasuk sukan tambahan.
Data:
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 |
Keputusan yang Diingini:
Memandangkan tatasusunan ["Bodyboarding", "Melayari"], pertanyaan harus mengembalikan medium tawaran dan semua kerana ia mengandungi kedua-dua sukan tertentu. Lampu tawaran tidak boleh dikembalikan kerana ia tidak termasuk kedua-dua sukan.
Pertanyaan Salah:
Pertanyaan berikut, yang mengumpulkan mengikut nama sukan dan memastikan betul-betul dua sukan termasuk dalam setiap tawaran, pulangan no keputusan:
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;
Penyelesaian:
Kumpulan pertanyaan yang betul mengikut ID tawaran dan bukannya nama sukan dan menyemak kiraan sukan berbeza yang disertakan dalam setiap tawaran menggunakan 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;
Pertanyaan ini akan mengembalikan medium tawaran dan kesemuanya kerana kedua-duanya termasuk kedua-dua yang ditentukan sukan.
Pelaksanaan 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
Atas ialah kandungan terperinci Bagaimana untuk Memilih Tawaran yang Mengandungi Semua Set Sukan (Tetapi Mungkin Lebih Banyak) dalam SQL?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!