Let’s say I have the following tables:
TAGS
id: integer
name: string
POSTS
id: integer
body: text
TAGGINGS
id: integer
tag_id: integer
post_id: integer
How would I go about writing a query that select all posts that are tagged with ALL of the following tags (name attribute of tags table): "Cheese", "Wine", "Paris", "Frace", "City", "Scenic", "Art"
See also: Sql query to find things with most specified tags (note: similar, but not a duplicate!)
Using IN:
Using a JOIN
Using EXISTS
Explanation
The crux of things is that the
COUNT(DISTINCT t.name)needs to match the number of tag names to ensure that all those tags are related to the post. Without the DISTINCT, there’s a risk that duplicates of one of the names could return a count of 7–so you’d have a false positive.Performance
Most will tell you the JOIN is optimal, but JOINs also risk duplicating rows in the resultset. EXISTS would be my next choice–no duplicate risk, and generally faster execution but checking the explain plan will ultimately tell you what’s best based on your setup and data.