假设这些表:
- 帖子ID,作者,日期,内容
- 标签ID,名称
- PostTags :post_id,tag_id
最后一个表通常被称为连接表,并促进了文章和标签之间的多对多关系。
SELECT p.*
FROM posts p
JOIN posttags pt ON p.id = pt.post_id
JOIN tags t ON pt.tag_id = t.id
WHERE t.name = 'sql'
基本上,认为许多一对多的关系,两个一对多关系的,因为这是他们如何在正常的RDBMS实现。所以上面的查询有一个从Posts到PostTag的一对多连接,另一个从Tags到PostTag。
我创建的PostTags表具有复合主键,即(post_id, tag_id)
。这种组合将是独一无二的。许多冷遇组合键,因此您会经常看到有人创建一个主键列:
- PostTags:ID,POST_ID,TAG_ID
两种方法是罚款。这在很大程度上是一个哲学上的差异。
更新:,如果你想选择所有具有特定标签,所有的标签这些帖子有那么帖子:
SELECT p.*
FROM posts p
JOIN posttags pt ON p.id = pt.post_id
JOIN tags t ON pt.tag_id = t.id
WHERE p.id IN
(SELECT post_id
FROM PostTags pt
JOIN tags t ON pt.tag_id = t.id
WHERE t.name = 'xyz')
另一种方式来做到这一点:
SELECT p.*
FROM posts p
JOIN posttags pt ON p.id = pt.post_id
JOIN tags t ON pt.tag_id = t.id
WHERE EXISTS
(SELECT post_id
FROM PostTags pt
JOIN tags t ON pt.tag_id = t.id
WHERE t.name = 'xyz'
AND pt.post_id = p.id)
哪个性能更好将需要测试,并可能因数据库供应商和版本而异。一个好的优化器(如Oracle)可能会优化它们以执行相同的操作。其他人可能不会。
现在,这将让你回行这样的:
Post 1, tag 1
Post 1, tag 2
Post 3, tag 2
Post 3, tag 3
所以你需要把它们混合起来,最好是在应用程序逻辑,而不是SQL。一些关系数据库管理系统有这种类型的供应商特定的扩展,比如MySQL的GROUP_CONCAT()
函数。
查看更新.... – cletus 2010-08-03 15:51:48
鉴于所选答案似乎是一个SQL解决方案而不是DQL,这个问题的标题不应该从DQL更改为SQL吗?我来到这里寻找一种方法来完成多对多的DQL查询,但这里没有任何内容。 – 2012-03-29 20:50:47