Mysql
 sql >> Base de données >  >> RDS >> Mysql

Sélectionner dans une relation plusieurs à plusieurs dans MySQL

Il y a deux façons de faire ça. Je préfère la première méthode, qui consiste à s'auto-joindre pour chaque tag :

SELECT l.*
FROM Locations l
JOIN LocationsTagsAssoc a1 ON a1.LocationID = l.ID
JOIN Tags t1 ON a1.TagID = t1.ID AND t1.Name = ?
JOIN LocationsTagsAssoc a2 ON a2.LocationID = l.ID
JOIN Tags t2 ON a2.TagID = t2.ID AND t2.Name = ?
JOIN LocationsTagsAssoc a3 ON a3.LocationID = l.ID
JOIN Tags t3 ON a3.TagID = t3.ID AND t3.Name = ?;

L'autre méthode fonctionne également, mais en utilisant GROUP BY dans MySQL a tendance à générer une table temporaire et les performances sont lentes :

SELECT l.*
FROM Locations l
JOIN LocationsTagsAssoc a ON a.LocationID = l.ID
JOIN Tags t ON a.TagID = t.ID
WHERE t.Name IN (?, ?, ?)
GROUP BY l.ID
HAVING COUNT(*) = 3;

Re commentaire de @Erikoenig :

Si vous voulez vous assurer qu'il n'y a pas de balises supplémentaires, vous pouvez procéder comme suit :

SELECT l.*
FROM Locations l
JOIN LocationsTagsAssoc a ON a.LocationID = l.ID
JOIN Tags t ON a.TagID = t.ID
GROUP BY l.ID
HAVING COUNT(*) = 3 AND SUM(t.Name IN (?, ?, ?)) = 3;

La suppression de la clause WHERE permet de compter les autres balises, s'il y en a. Ainsi, le COUNT() peut être supérieur à 3.

Ou si le nombre est exactement de trois balises, mais que certaines de ces trois balises ne sont pas les bonnes balises, la condition SUM() dans la clause HAVING s'assure que les trois balises souhaitées sont présentes dans le groupe.