Utilizzo di 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)
Utilizzo di un 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
Utilizzo di 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)
Spiegazione
Il punto cruciale è che il COUNT(DISTINCT t.name)
deve corrispondere al numero di nomi di tag per garantire che tutti quei tag siano correlati al post. Senza DISTINCT, c'è il rischio che i duplicati di uno dei nomi possano restituire un conteggio di 7, quindi avresti un falso positivo.
Prestazioni
La maggior parte ti dirà che JOIN è ottimale, ma i JOIN rischiano anche di duplicare le righe nel set di risultati. EXISTS sarebbe la mia prossima scelta:nessun rischio duplicato e un'esecuzione generalmente più rapida, ma controllando il piano di spiegazione alla fine ti dirà cosa è meglio in base alla tua configurazione e ai tuoi dati.