【问题标题】:JOIN instead of subquery for related tagsJOIN 而不是相关标签的子查询
【发布时间】:2010-12-19 14:28:08
【问题描述】:

我有三张桌子,bookmarkstagtaggingtagging 是将标签链接到书签的关联表。我想选择相关的标签。当前的查询需要很长时间才能运行,但我无法理解可以替换子查询的 JOIN,该子查询选择使用特定标签 ID 标记的所有相关书签。

SELECT ta.name, count(*) 
FROM tagging t2 
JOIN tag ta ON t2.tag_id=ta.id  
WHERE t2.bookmark_id IN (
   SELECT bookmark_id 
   FROM tagging t1 
   WHERE t1.tag_id IN (1, 7) 
   GROUP BY t1.bookmark_id 
   HAVING COUNT(t1.id) = 2
) 
GROUP BY ta.id

这是该查询的EXPLAIN 的结果:

1   PRIMARY            ta  index PRIMARY    PRIMARY         8   NULL         3   
1   PRIMARY            t2  ref   tag_id_idx tag_id_idx      8   blinkz.ta.id 89   Using where
2   DEPENDENT SUBQUERY t1  index tag_id_idx bookmark_id_idx 8   NULL         71   Using where 

我在tagging 表中有一个bookmark_idtag_id 字段的索引。 tag 表有一个名为 id 的主键

如何优化此查询,最好使用 JOIN 而不是子查询?

【问题讨论】:

    标签: sql mysql join tagging subquery


    【解决方案1】:

    性能不佳是由于bug in MySQL 希望很快得到修复。在那之前试试这个:

    SELECT tag.name, COUNT(*) AS cnt
    FROM tagging T1
    JOIN tag
    ON T1.tag_id = tag.id  
    JOIN (
       SELECT bookmark_id 
       FROM tagging
       WHERE tag_id IN (1, 7) 
       GROUP BY bookmark_id 
       HAVING COUNT(id) = 2
    ) T2
    ON T1.bookmark_id = T2.bookmark_id
    GROUP BY tag.id
    

    我假设(bookmark_id, tag_id) 上有一个独特的约束。

    【讨论】:

    • 效果很好!但是有一个小错误: HAVING 应该是 COUNT(tagging.id) 而不是 COUNT(T1.id)
    • @chiborg:谢谢,已修复。顺便说一句,如果 id 字段不是 NULL(它可能是),那么你可以只写 COUNT(*)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-06
    • 1970-01-01
    • 1970-01-01
    • 2013-02-07
    • 2019-06-06
    • 2021-04-25
    相关资源
    最近更新 更多