Suppose I have the following three tables expressing a relationship where posts are given tags (a many-to-many relationship):
create table posts (id integer, content text, primary key (id));
create table tags (tag varchar(30), description text, primary key (tag));
create table post_tags (post_id integer, tag varchar(10),
primary key (post_id, tag),
foreign key (post_id) references posts (id),
foreign key (tag) references tags (tag));
Now suppose I want to find all posts with exactly the tags {clever,interesting}, and no others.
Here is my failed attempt. It finds posts which have the tags {clever,interesting}, but it also finds posts with the tags {clever,interesting,annoying} or {clever,interesting,unethical}.
select t1.post_id from post_tags as t1
inner join post_tags as t2 on t2.post_id=t1.post_id
where t1.tag='clever' and t2.tag='interesting';
I’m open to any suggestions for changing the structure to make this operation easier. However, I want to avoid things like adding a comma-separated list of tags in the posts table.
This is an exact relational division problem.
In SQL Server a well performing method (assuming unique constraint on
post_id,tag) isSo I wouldn’t rule out the idea of using
GROUP_CONCATin theHAVINGinstead.