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.