假设我有以下三个表,表示帖子被赋予标签的关系(多对多关系):
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));
现在假设我想查找所有标签{clever,interesting},而不是其他帖子。
这是我失败的尝试。它会找到包含{clever,interesting}标签的帖子,但它也会找到包含{聪明,有趣,烦人}或{聪明,有趣,不道德}标签的帖子。
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';
我愿意接受任何改变结构的建议,以使这项操作更容易。但是,我想避免在posts
表中添加以逗号分隔的标记列表。
答案 0 :(得分:3)
这是一个确切的关系划分问题。
在SQL Server中,well performing方法(假设post_id,tag
上有唯一约束)是
SELECT post_id
FROM post_tags
GROUP BY post_id
HAVING MIN(CASE
WHEN Keyword IN ( 'clever', 'interesting' ) THEN 1
ELSE 0
END) = 1
AND SUM(CASE
WHEN Keyword IN ( 'clever', 'interesting' ) THEN 1
ELSE 0
END) = 2
所以我不排除在GROUP_CONCAT
中使用HAVING
的想法。
HAVING GROUP_CONCAT(DISTINCT Keyword ORDER BY Keyword) = 'clever,interesting'
答案 1 :(得分:2)
应该可以使用NOT EXISTS
,例如,
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'
and not exists (
select *
from post_tags t3
where
t3.tag not in ('clever', 'interesting')
and t3.post_id = t1.post_id
)