Reputation: 1575
I have a many to many relationship between stories
and tags
, the table created to hold the relationship is taxonomies
. I want to search all the stories that have all the given tags.
The query I'm using so far is this one, of course it doesn't work for me, it returns all stories that contain any of the given tags, I want to show stories that contain all the defined tags.
SELECT stories.* FROM `stories`
JOIN `taxonomies` ON `stories`.id = `taxonomies`.`story_id`
JOIN `tags` ON `tags`.id = `taxonomies`.tag_id
WHERE `tags`.name = 'tag 1' OR `tags`.name = 'tag 2' /* ... */
GROUP BY stories.id
Upvotes: 2
Views: 71
Reputation: 26784
I think you want this query
SELECT stories.id FROM `stories`
JOIN `taxonomies` ON `stories`.id = `taxonomies`.`story_id`
JOIN `tags` ON `tags`.id = `taxonomies`.tag_id
GROUP BY stories.id
HAVING SUM(`tags`.name = 'tag 1')>0
AND SUM(`tags`.name = 'tag 2')>0
Upvotes: 4
Reputation: 85056
Do you know the number of tags you are checking? If so, could you use a HAVING to confirm that the number of matches for stories.id
matches the total number of tags? Something like this:
SELECT stories.id, COUNT(stories.id)
FROM `stories`
JOIN `taxonomies` ON `stories`.id = `taxonomies`.`story_id`
JOIN `tags` ON `tags`.id = `taxonomies`.tag_id
WHERE `tags`.name = 'tag 1' OR `tags`.name = 'tag 2' /* ... */
GROUP BY stories.id
HAVING COUNT(stories.id) = @numberOfTags
Upvotes: 1
Reputation: 10683
Simplest way to do this will be:
SELECT stories.* FROM `stories`
JOIN `taxonomies` ON `stories`.id = `taxonomies`.`story_id`
JOIN `tags` ON `tags`.id = `taxonomies`.tag_id
WHERE `tags`.name = 'tag 1'
GROUP BY stories.id
intersect
SELECT stories.* FROM `stories`
JOIN `taxonomies` ON `stories`.id = `taxonomies`.`story_id`
JOIN `tags` ON `tags`.id = `taxonomies`.tag_id
WHERE `tags`.name = 'tag 2'
GROUP BY stories.id
Upvotes: -1