"SQL où l'ensemble joint doit contenir toutes les valeurs mais peut en contenir davantage"
Comprendre l'exigence
Considérez trois tables liées : offres, sports et offres_sports, jointes via des relations has_and_belongs_to_many. L'objectif est de sélectionner des offres qui incluent un éventail spécifié de sports, les offres devant contenir tous les sports spécifiés mais pouvant comporter des sports supplémentaires.
Solution potentielle
Une L'approche consiste à utiliser une combinaison de clauses JOIN, WHERE, GROUP BY et HAVING pour filtrer les résultats en fonction des conditions requises. Plus précisément :
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;
Cette requête rejoint d'abord les trois tables pour récupérer les offres et leurs sports associés. La clause WHERE limite la recherche aux sports portant des noms spécifiés. La clause GROUP BY regroupe les résultats par ID d'offre et la clause HAVING garantit que seules les offres contenant tous les sports spécifiés sont sélectionnées.
Implémentation ActiveRecord améliorée
L'ActiveRecord fourni La solution peut être affinée davantage pour améliorer l'efficacité :
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
Cette méthode utilise le chaînage pour effectuer les opérations nécessaires, notamment JOIN, WHERE, GROUP BY et HAVING, en une seule requête. Il simplifie également la clause HAVING en utilisant un espace réservé de point d'interrogation (?) pour transmettre dynamiquement la valeur de comptage attendue.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!