0

我有以下查询,它使用引用表tags_titlestags_blogs来与包含标签的表进行比较,称为tags。标签本身保存在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
4

1 回答 1

4

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

您的问题的简单解决方案是使用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 中的列表。前一种方法不使用索引进行过滤。后者将(如果有合适的可用)。

于 2013-07-27T13:43:01.237 回答