Има два начина да направите това. Предпочитам първия начин, който е да се самоприсъединявам към всеки маркер:
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 = ?;
Другият начин също работи, но използвайки GROUP BY
в MySQL има тенденция да създава временна таблица и производителността е бавна:
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;
Повторен коментар от @Erikoenig:
Ако искате да сте сигурни, че няма допълнителни тагове, можете да го направите по следния начин:
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;
Изваждането на клаузата WHERE позволява да се преброят други тагове, ако има такива. Така че COUNT() може да е по-голямо от 3.
Или ако броят е точно три маркера, но някои от тези три не са правилните тагове, тогава условието SUM() в клаузата HAVING гарантира, че всичките три маркера, които искате, присъстват в групата.