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

Besoin d'aide avec une requête sql pour trouver des choses étiquetées avec toutes les balises spécifiées

Utiliser IN :

SELECT p.*
  FROM POSTS p
 WHERE p.id IN (SELECT tg.post_id
                  FROM TAGGINGS tg
                  JOIN TAGS t ON t.id = tg.tag_id
                 WHERE t.name IN ('Cheese','Wine','Paris','Frace','City','Scenic','Art')
              GROUP BY tg.post_id
                HAVING COUNT(DISTINCT t.name) = 7)

Utiliser une jointure

SELECT p.*
  FROM POSTS p
  JOIN (SELECT tg.post_id
          FROM TAGGINGS tg
          JOIN TAGS t ON t.id = tg.tag_id
         WHERE t.name IN ('Cheese','Wine','Paris','Frace','City','Scenic','Art')
      GROUP BY tg.post_id
        HAVING COUNT(DISTINCT t.name) = 7) x ON x.post_id = p.id

Utiliser EXISTE

SELECT p.*
  FROM POSTS p
 WHERE EXISTS (SELECT NULL
                 FROM TAGGINGS tg
                 JOIN TAGS t ON t.id = tg.tag_id
                WHERE t.name IN ('Cheese','Wine','Paris','Frace','City','Scenic','Art')
                  AND tg.post_id = p.id
             GROUP BY tg.post_id
               HAVING COUNT(DISTINCT t.name) = 7)

Explication

L'essentiel est que le COUNT(DISTINCT t.name) doit correspondre au nombre de noms de balises pour s'assurer que toutes ces balises sont liées à la publication. Sans le DISTINCT, il y a un risque que les doublons de l'un des noms renvoient un nombre de 7 - vous auriez donc un faux positif.

Performances

La plupart vous diront que le JOIN est optimal, mais les JOIN risquent également de dupliquer des lignes dans le jeu de résultats. EXISTS serait mon prochain choix - pas de risque de duplication et une exécution généralement plus rapide, mais la vérification du plan d'explication vous indiquera finalement ce qui est le mieux en fonction de votre configuration et de vos données.