Использование 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)
Использование JOIN
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
Использование EXISTS
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)
Объяснение
Суть в том, что COUNT(DISTINCT t.name)
должно соответствовать количеству имен тегов, чтобы гарантировать, что все эти теги связаны с постом. Без DISTINCT существует риск, что дубликаты одного из имен могут вернуть счетчик 7, так что вы получите ложное срабатывание.
Производительность
Большинство скажет вам, что соединение является оптимальным, но соединения также рискуют дублировать строки в наборе результатов. EXISTS будет моим следующим выбором - нет дублирующегося риска и, как правило, более быстрое выполнение, но проверка плана объяснения в конечном итоге скажет вам, что лучше всего, исходя из ваших настроек и данных.