Można to zrobić na dwa sposoby. Wolę pierwszy sposób, który polega na samodzielnym dołączaniu do każdego tagu:
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 = ?;
Drugi sposób również działa, ale używając GROUP BY
w MySQL ma tendencję do tworzenia tymczasowej tabeli, a wydajność jest niska:
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;
Ponownie komentarz od @Erikoenig:
Jeśli chcesz się upewnić, że nie ma żadnych dodatkowych tagów, możesz to zrobić w ten sposób:
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;
Wyjęcie klauzuli WHERE umożliwia zliczanie innych tagów, jeśli takie istnieją. Tak więc LICZBA() może być większa niż 3.
Lub jeśli liczba wynosi dokładnie trzy znaczniki, ale niektóre z nich nie są prawidłowymi znacznikami, wówczas warunek SUM() w klauzuli HAVING zapewnia, że wszystkie trzy żądane znaczniki znajdują się w grupie.