MySQL内部联接管理count()行为

艾米·内维尔(Amy Neville)

我有以下查询,该查询使用参考表tag_titlestags_blogs与其中包含标签的表进行比较,该表称为tag标签本身保存在t.label列中

我的问题是有时它count()过多total_matches通常,在tags_titles和tags_blogs中可以找到引用的标签时。是否有任何方法可以使内部联接互斥,或采用其他解决方案,以使对t.label列的实际匹配计数准确无误?

SELECT b.blog_id AS id, b.title AS title, b.body AS body, COUNT(t.label) AS total_matches, b.creation_time AS creation_time, '1' AS type
FROM tags AS t 
INNER JOIN tags_titles AS tt
ON tt.tag_id = t.tag_id
INNER JOIN tags_blogs AS tb
ON tb.tag_id = t.tag_id
INNER JOIN blogs AS b
ON tt.blog_id=b.blog_id OR tb.blog_id=b.blog_id
WHERE t.label IN ($in) AND b.title IS NOT NULL
GROUP BY id, title, body, creation_time, type
戈登·利诺夫(Gordon Linoff)

您的问题是标题有一个标签列表,博客有一个标签列表,并且每个博客都获得这些标签的笛卡尔积。

解决您的问题的简单方法是使用count(distinct)

SELECT b.blog_id AS id, b.title AS title, b.body AS body, COUNT(distinct t.label) AS total_matches,
       b.creation_time AS creation_time, '1' AS type
FROM tags AS t 
INNER JOIN tags_titles AS tt
ON tt.tag_id = t.tag_id
INNER JOIN tags_blogs AS tb
ON tb.tag_id = t.tag_id
INNER JOIN blogs AS b
ON tt.blog_id=b.blog_id OR tb.blog_id=b.blog_id
WHERE t.label IN ($in) AND b.title IS NOT NULL
GROUP BY id, title, body, creation_time, type;

在更复杂的场景中,有时您需要在联接之前沿单独的维度进行聚合。

您还有另一个问题t.label in ($in)这不适用于in。相反,您可以使用:

find_in_set(t.label, $in) > 0;

或在SQL中直接替换列表。前一种方法不使用索引进行过滤。后者将(如果合适的话)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章