Korzystanie z 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)
Korzystanie z 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
Korzystanie z 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)
Wyjaśnienie
Sednem rzeczy jest to, że COUNT(DISTINCT t.name)
musi odpowiadać liczbie nazw tagów, aby upewnić się, że wszystkie te tagi są powiązane z postem. Bez DISTINCT istnieje ryzyko, że duplikaty jednego z nazwisk mogą zwrócić liczbę 7 – więc otrzymasz fałszywy alarm.
Wydajność
Większość powie, że JOIN jest optymalne, ale JOIN ryzykuje również powielanie wierszy w zestawie wyników. EXISTS to mój następny wybór — bez podwójnego ryzyka i ogólnie szybsze wykonanie, ale sprawdzenie planu wyjaśnień ostatecznie powie, co jest najlepsze w oparciu o konfigurację i dane.