代码之家  ›  专栏  ›  技术社区  ›  smoove

MySQL子选择问题

  •  1
  • smoove  · 技术社区  · 17 年前

    我有两个问题要问 相关标签 从MySQL数据库中,一个有效,一个无效,我的问题是:“为什么?”

    问题: 在执行第一个查询时,MySQL服务器将获得100%的CPU使用率,必须重新启动才能再次运行。

    查询1 (不起作用):

    SELECT tags.*, COUNT(ct.company_id) AS count
    FROM company2tag ct, tags
    WHERE ct.company_id IN (
        SELECT ct.company_id FROM company2tag ct
        WHERE ct.tag_id = 18
        GROUP BY ct.company_id
        HAVING COUNT(ct.company_id) = 1
    )
    AND tags.id != 18
    AND tags.id = ct.tag_id
    GROUP BY ct.tag_id
    ORDER BY count DESC
    LIMIT 5;
    

    查询2 (作品):

    SELECT tags.*, COUNT(ct.company_id) AS count
    FROM company2tag ct, tags
    WHERE ct.company_id IN (5864, 5870, 6140, 6221, 6268)
        AND tags.id != 18
        AND tags.id = ct.tag_id
    GROUP BY ct.tag_id
    ORDER BY count DESC
    LIMIT 5;
    

    据我所知,上面的两个查询完全相同,唯一的区别是第一个查询通过一个嵌套select检索其“company_id”。

    怎么会这样?

    2 回复  |  直到 17 年前
        1
  •  3
  •   Powerlord    17 年前

    首先,您可能在第一个查询中遇到问题,因为有两个表的别名是CT…一个在外部查询中,一个在子查询中。

    其次,可以将in重写为join:

    SELECT tags.*, COUNT(ct.company_id) AS count
    FROM company2tag ct
    INNER JOIN tags ON tags.id = ct.tag_id
    INNER JOIN (
        SELECT company_id FROM company2tag
        WHERE tag_id = 18
        GROUP BY company_id
        HAVING COUNT(company_id) = 1
    ) ctf ON ct.company_id = ctf.company_id
    WHERE tags.id != 18
    GROUP BY ct.tag_id
    ORDER BY count DESC
    LIMIT 5;
    

    注意,我还没有测试过这个。

        2
  •  2
  •   Quassnoi    17 年前

    MySQL 优化不是很好 IN 条件。

    第一个查询中的条件不能轻易重写为 EXISTS 这就是为什么 MySQL 检查每行的结果。

    如果你想选择 company_id 这是在 tag 18 ,最好将此查询重写为:

    SELECT  tags.*, COUNT(company_id) AS count
    FROM    company2tag ct
    JOIN    tags
    ON      tags.id = ct.tag_id
    WHERE   ct.tag_id <> 18
            AND NOT EXISTS
            (
            SELECT  NULL
            FROM    company2tag cti
            WHERE   cti.tag_id = 18
                    AND cti.company_id = ct.company_id
            LIMIT 1, 1
            )
    GROUP BY
            ct.tag_id
    ORDER BY
            count DESC
    

    这里的主要想法是你不需要 COUNT(*) :只需检查是否至少存在两个值就足够了。

    有关类似问题,请参阅我的博客中的这篇文章:

    具有以下索引:

    CREATE INDEX ix_company2tag_tag_company_id ON company2tag (tag_id, company_id)
    

    将大大改进此查询。