查询以查找具有一组精确标签的帖子(多对多关系)

时间:2012-01-25 23:10:56

标签: mysql sql

假设我有以下三个表,表示帖子被赋予标签的关系(多对多关系):

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表中添加以逗号分隔的标记列表。

2 个答案:

答案 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
)