MySQL如何通过多个1:n关联表查询指定分类下的可用标签
问题说明
现有MySQL数据库包含Categories、Posts、Tags三张数据表,Posts表与Tags、Categories表均为1:N关联关系:单篇Post仅对应唯一category、唯一tag。要求不直接关联Categories与Tags表的前提下,查询指定分类下的所有可用标签。
示例表结构与测试数据如下:
-- Posts表 post ID | category ID | tag ID ---------------------------- 1 | 1 | 1 2 | 1 | 2 3 | 2 | 1 4 | 3 | 3 -- Categories表 category ID | name -------------------- 1 | video 2 | image 3 | code -- Tags表 tag ID | name -------------------- 1 | funny 2 | info 3 | script
预期查询效果:
查询分类为
video时,返回标签funny、info;查询分类为code时,仅返回标签script。
实现方案
核心思路是用Posts表做两表的关联中转,全程不写Categories和Tags的直接关联条件,两种常用写法都能满足要求:
写法1:JOIN关联(推荐,可读性更好)
SELECT DISTINCT t.`name` AS tag_name FROM Categories c INNER JOIN Posts p ON c.`category ID` = p.`category ID` INNER JOIN Tags t ON p.`tag ID` = t.`tag ID` WHERE c.`name` = 'video'; -- 替换此处的分类名即可查询对应分类的标签
注意点:
- 因为示例里的字段名带空格,所有字段名都加了反引号转义,如果你实际建表用的是无空格的命名(比如
category_id),调整反引号内的字段名即可 - 加
DISTINCT是为了去重:如果同一个分类下有多篇文章绑定了同一个标签,不会返回重复的标签名 - 关联路径是
Categories -> Posts -> Tags,没有直接关联Categories和Tags,完全符合要求
写法2:子查询嵌套
习惯写子查询的话可以用这个写法,InnoDB引擎下执行效率和JOIN写法基本一致:
SELECT `name` AS tag_name FROM Tags WHERE `tag ID` IN ( SELECT DISTINCT `tag ID` FROM Posts WHERE `category ID` = ( SELECT `category ID` FROM Categories WHERE `name` = 'video' -- 替换为目标分类名 ) );
结果验证
用测试数据跑上述SQL:
- 把WHERE条件的分类名改为
video,返回结果为funny、info - 把WHERE条件的分类名改为
code,返回结果为script
完全匹配预期效果。
内容的提问来源于stack exchange,提问作者nn3112337
相关产品推荐
相关产品推荐

