Toho lze dosáhnout dvěma způsoby. Dávám přednost prvnímu způsobu, kterým je samostatné připojení pro každý tag:
SELECT l.*
FROM Locations l
JOIN LocationsTagsAssoc a1 ON a1.LocationID = l.ID
JOIN Tags t1 ON a1.TagID = t1.ID AND t1.Name = ?
JOIN LocationsTagsAssoc a2 ON a2.LocationID = l.ID
JOIN Tags t2 ON a2.TagID = t2.ID AND t2.Name = ?
JOIN LocationsTagsAssoc a3 ON a3.LocationID = l.ID
JOIN Tags t3 ON a3.TagID = t3.ID AND t3.Name = ?;
Druhý způsob také funguje, ale pomocí GROUP BY
v MySQL má tendenci vytvářet dočasnou tabulku a výkon je pomalý:
SELECT l.*
FROM Locations l
JOIN LocationsTagsAssoc a ON a.LocationID = l.ID
JOIN Tags t ON a.TagID = t.ID
WHERE t.Name IN (?, ?, ?)
GROUP BY l.ID
HAVING COUNT(*) = 3;
Znovu komentář od @Erikoenig:
Pokud se chcete ujistit, že tam nejsou žádné další značky, můžete to udělat takto:
SELECT l.*
FROM Locations l
JOIN LocationsTagsAssoc a ON a.LocationID = l.ID
JOIN Tags t ON a.TagID = t.ID
GROUP BY l.ID
HAVING COUNT(*) = 3 AND SUM(t.Name IN (?, ?, ?)) = 3;
Vyjmutí klauzule WHERE umožňuje počítat další značky, pokud nějaké existují. Takže COUNT() může být větší než 3.
Nebo pokud jsou počet přesně tři značky, ale některé z těchto tří nejsou správné značky, pak podmínka SUM() v klauzuli HAVING zajistí, že všechny tři požadované značky budou ve skupině přítomny.