Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL to find articles with ALL of a set of tags

Tags:

sql

Finding articles with ANY of a set of tags is a relatively simple join, and has been discussed already: Best DB (MySQL) structure: Articles which contain favored tags

But what if I'm searching, and want to find articles with ALL of a set of tags?

For specificity, assume the following tables:

CREATE TABLE `articles` (
   `id` INT NOT NULL
);

CREATE TABLE `applied_tags` (
   `tag_id` INT NOT NULL,
   `article_id` INT NOT NULL
);

CREATE TABLE `search_tags` (
   `search_id` INT NOT NULL,
   `tag_id` TAG NOT NULL
);

I came up with this, which I think might work, but it's massive, ugly, and kinda unclear, so I figure there must be a better way:

Select articles.id from articles
where
 ( select count(*) from applied_tags
   where applied_tags.article_id == articles.id
     and applied_tags.tag_id in (select search_tags.tag_id from search_tags where search_tags.search_id == <input>) 
     ==
 (select count(*) from search_tags where search_tags.search_id == <input>)

(Essentially, count if the number of relevant tags is the expected value.)

like image 503
me22 Avatar asked Sep 09 '09 15:09

me22


1 Answers

select article_id
from  applied_tags 
where tag_id in (<input tag set here>)
group by article_id
having count(*) = <count of input tags>

This should do it. I won't swear it's the most efficient way, but it will do what you want, assuming that tag_id + article_id is the primary key on applied_tags. If it's not (i.e., you can have duplicate tags) all bets are off.

like image 108
Harper Shelby Avatar answered Sep 24 '22 19:09

Harper Shelby