これを行うには2つの方法があります。私は最初の方法を好みます。それは、タグごとに自己参加することです:
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より大きい可能性があります。
または、カウントが正確に3つのタグであるが、これら3つのタグの一部が正しいタグではない場合、HAVING句のSUM()条件により、必要な3つのタグすべてがグループに存在することが確認されます。