sql >> Base de Datos >  >> RDS >> Mysql

Necesito ayuda con la consulta sql para encontrar cosas etiquetadas con todas las etiquetas especificadas

Usando EN:

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)

Usando un ÚNETE

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

Usando 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)

Explicación

El quid de las cosas es que el COUNT(DISTINCT t.name) debe coincidir con la cantidad de nombres de etiquetas para asegurarse de que todas esas etiquetas estén relacionadas con la publicación. Sin DISTINCT, existe el riesgo de que los duplicados de uno de los nombres devuelvan un recuento de 7, por lo que tendría un falso positivo.

Rendimiento

La mayoría le dirá que JOIN es óptimo, pero JOIN también corre el riesgo de duplicar filas en el conjunto de resultados. EXISTS sería mi próxima opción:sin riesgo de duplicación y, en general, una ejecución más rápida, pero verificar el plan de explicación finalmente le dirá qué es lo mejor en función de su configuración y datos.