Mysql HABTM查询帮助
“文章”和“标签”之间存在HABTM关系 问题:我只寻找同时带有“sports”和“Outdoor”标签的文章,而不是只带有其中一个标签的文章 我试过这个:Mysql HABTM查询帮助,mysql,sql,has-and-belongs-to-many,sql-match-all,Mysql,Sql,Has And Belongs To Many,Sql Match All,“文章”和“标签”之间存在HABTM关系 问题:我只寻找同时带有“sports”和“Outdoor”标签的文章,而不是只带有其中一个标签的文章 我试过这个: SELECT DISTINCT article.id, article.name FROM articles inner JOIN tags ON (tags.name IN ('outdoors', 'sports') inner JOIN articles_tags ON articles_tags.article_id = artic
SELECT DISTINCT article.id, article.name FROM articles
inner JOIN tags ON (tags.name IN ('outdoors', 'sports')
inner JOIN articles_tags ON articles_tags.article_id = article.id AND articles_tags.tag_id = tags.id
…但它给我的文章只有体育类、户外类和体育+户外类
问题什么是正确的查询?(我正在使用MySQL)试试这个:
SELECT a1.id, a1.name FROM articles a1
JOIN tags t1 ON t1.name ='outdoors'
JOIN articles_tags at1 ON at1.article_id = a1.id AND at1.tag_id = t1.id
JOIN tags t2 ON t2.name = 'sports'
JOIN articles_tags at2 ON at2.article_id = a1.id AND at2.tag_id = t2.id
有两种常见的解决方案
- 第一种解决方案使用
计算每篇文章中与“户外”或“运动”匹配的标签,然后只返回两个标签都有的组groupby
对于某些人来说,此解决方案更具可读性,并且添加值更简单。但是MySQL中的SELECT a.id, a.name FROM articles AS a INNER JOIN articles_tags AS at ON (a.id = at.article_id) INNER JOIN tags AS t ON (t.id = at.tag_id) WHERE t.name IN ('outdoors', 'sports') GROUP BY a.id HAVING COUNT(DISTINCT t.name) = 2;
查询往往会产生一个临时表,这会影响性能groupby
- 另一种解决方案为每个不同的标记使用一个
。通过使用内部联接,查询自然会限制到与指定的所有标记匹配的项目JOIN
假设SELECT a.id, a.name FROM articles AS a INNER JOIN articles_tags AS at1 ON (a.id = at1.article_id) INNER JOIN tags AS t1 ON (t1.id = at1.tag_id AND t1.name = 'outdoors') INNER JOIN articles_tags AS at2 ON (a.id = at2.article_id) INNER JOIN tags AS t2 ON (t2.id = at2.article_id AND t2.name = 'sports');
和tags.name
都有articles\u标记(article\u id,tag\u id)
约束,则不需要UNIQUE
查询修饰符 假设您已经定义了适当的索引,那么这种类型的查询在MySQL上的优化效果往往优于DISTINCT
解决方案groupby
如果你在评论中提出了后续问题,我会这样做:
SELECT a.id, a.name, GROUP_CONCAT(t3.tag) AS all_tags
FROM articles AS a
INNER JOIN articles_tags AS at1 ON (a.id = at1.article_id)
INNER JOIN tags AS t1 ON (t1.id = at1.tag_id AND t1.name = 'outdoors')
INNER JOIN articles_tags AS at2 ON (a.id = at2.article_id)
INNER JOIN tags AS t2 ON (t2.id = at2.article_id AND t2.name = 'sports');
INNER JOIN articles_tags AS at3 ON (a.id = at3.article_id)
INNER JOIN tags AS t3 ON (t3.id = at3.article_id);
GROUP BY a.id;
这仍然只能找到同时具有“Outdoor”和“sports”标签的文章,但它会进一步将这些文章加入到其所有标签中
这将为每篇文章返回多行(每个标签一行),因此我们使用
groupby
再次将每篇文章减少到一行。返回相应组中以逗号分隔的值列表。感谢您的解释。。。此外,在该查询中是否可以返回与匹配文章关联的所有标记?