文章和标签是典型的一对多的关系, 也就是说每一篇文章都可以包含多个标签, 如图:
每一篇文章都可以包含多个标签
下面问题来了: 如何查询 tag_id 同时包含 1,2,3 的 article_id? 此问题看似简单, 实际上也非常简单, 本来是一道送分题, 但是很多人却做不出来!
方法一:
- SELECT article_id FROM (
- SELECT article_id, GROUP_CONCAT(tag_id ORDER BY tag_id) tag_ids
- FROM articles_tags
- WHERE article_id in (1, 2, 3)
- GROUP BY article_id
- ) t WHERE tag_ids LIKE '%1,2,3%';
说明: 此方法利用 GROUP_CONCAT 来解决问题, 不过鉴于 GROUP_CONAT 是 MySQL 专有函数, 出于通用型的考虑, 我们并不推荐使用此方法.
方法二:
- SELECT at1.article_id
- FROM (
- SELECT *
- FROM articles_tags
- WHERE tag_id = 1
- ) at1
- JOIN articles_tags at2 ON at1.article_id = at2.article_id AND at2.tag_id = 2
- JOIN articles_tags at3 ON at1.article_id = at3.article_id AND at3.tag_id = 3
说明: 此方法利用多次 JOIN 来解决问题, 中规中矩.
方法三:
- SELECT article_id
- FROM articles_tags
- WHERE tag_id in (1, 2, 3)
- GROUP BY article_id
- HAVING COUNT(*) = 3
说明: 此方法利用 GROUP 和 HAVING 来解决问题, 非常简洁.
关于一对多关系的查询问题, 实际情况可能会更复杂一些, 让我们扩展一下本题:
如何查询 tag_id 包含 1,2 但不包含 3 的 article_id?
如何查询 tag_id 包含 1,2,3 中至少两个的 article_id?
如果你理解了前面介绍的几种方法, 那么解决这些扩展问题并不困难, 不要固守某一种方法, 要根据情况选择合适的方法, 篇幅所限, 恕不赘述, 就留给大家自己解决吧.
来源: http://www.tuicool.com/articles/3eIVfeB