多对多表SQL选择问题

时间:2010-08-31 09:23:01

标签: php sql mysql

我有两个相关的表,为了这个问题的目的,它将被称为poststagsposts包含各种帖子,例如在社区论坛系统中找到的帖子。 tags包含一组唯一的标记,这些标记在服务器遇到系统中尚未存在的新标记时添加。每个标签只有一个条目。

posts可以有多个标记,而tags可以有多个帖子作为对它的引用。为了来回处理这些引用,我创建了一个表位于这两个表之间,称为posttagsposttags包含对tag ID和post ID的引用。这就是维持多对多关系的方式。

现在,关于这个问题。我需要能够根据标签选择帖子。当只有一个标记要搜索时,这是一个简单的连接,但我对如何处理多个标记感到茫然。例如,我需要能够搜索数据库并获得具有列表中所有标记的结果(例如,“php,mysql,sql”),而不使用循环内的SQL或任何其他低性能选项。

我不知道该怎么做。有人能指出我正确的方向吗?

谢谢!

2 个答案:

答案 0 :(得分:3)

您可以使用以下方法,3是请求标签的数量。

SELECT PostId
FROM posttags pt, tags t
WHERE p.Id = pt.PostId
  AND t.Id = pt.TagId
  AND tagname In ('php', 'mysql', 'sql')
group by PostId
having count(*) = 3

或者您可以按顺序对请求的标签进行排序并使用以下内容:

Select * from Posts p,
(  
 SELECT PostId, GROUP_CONCAT(tagname ORDER BY tag_name DESC SEPARATOR ' ') Tags
 FROM posttags pt, tags t
 WHERE p.Id = pt.PostId
   AND t.Id = pt.TagId
 GROUP BY PostId

)t    在哪里.PostId = p.Id      AND t.Tags ='mysql php sql'

但您需要对标签进行排序

答案 1 :(得分:1)

如果您要选择在给定集中包含所有标记的帖子,您可以使用“计数”策略:

SELECT
  p.*
FROM tags t
LEFT JOIN posttags pt
  ON pt.tag_id = t.tag_id
LEFT JOIN posts p
  ON p.post_id = pt.post_id
WHERE
  tags.tag IN ('php', 'mysql', 'sql')
GROUP BY p.post_id
HAVING COUNT(tags.tag_id) = 3;

当然,如果你更改了套装,数字“3”应该改为套装中的元素数量。