MySQL 在子子查询中用连接替换 IN 和 EXISTS

标签 mysql join inner-join exists

因此,此查询当前在网上商店中用于检索有关文章的技术数据。 除了最近显示的产品数量增加导致某些类别的加载时间过长之外,它已经很好地达到了它的目的。

对于最差的页面之一,这个(以及其他一些查询)被请求了大约 80 次。

我最近才知道 MySQL 不会优化没有依赖参数的子查询只运行一次。

因此,如果有人可以帮助我解决其中一个问题并解释如何将 in 和 exists 替换为连接,我可能能够自己更改其他的。

select distinct criteria.cri_id, des_texts.tex_text, article_criteria.acr_value, article_criteria.acr_kv_des_id
from article_criteria, designations, des_texts, criteria, articles
where article_criteria.acr_cri_id = criteria.cri_id
and article_criteria.acr_art_id = articles.art_id
and articles.art_deliverystatus = 1
and criteria.cri_des_id = designations.des_id
and designations.des_lng_id = 9
and designations.des_tex_id = des_texts.tex_id
and criteria.cri_id = 328
and article_criteria.acr_art_id IN (Select distinct link_art.la_art_id
  from link_art, link_la_typ
  where link_art.la_id = link_la_typ.lat_la_id
  and link_la_typ.lat_typ_id = 17484
  and link_art.la_ga_id IN (Select distinct link_ga_str.lgs_ga_id
    from link_ga_str, search_tree
    where link_ga_str.lgs_str_id = search_tree.str_id
    and search_tree.str_type = 1
    and search_tree.str_id = 10132
    and EXISTS (Select *
      from link_la_typ
      where link_la_typ.lat_typ_id = 17484
      and link_ga_str.lgs_ga_id = link_la_typ.lat_ga_id)))
order by article_criteria.acr_value

我认为这个是带有子子子查询的主要坏人

我只是注意到我可以删除最后一个 exist 并且仍然得到相同的结果但没有增加速度,虽然这不是问题的一部分;)我会弄清楚我是否仍然需要那部分。

感谢任何帮助或指点,如果我遗漏了一些有用的信息,也请告诉我。

最佳答案

我认为这是等价的:

SELECT DISTINCT c.cri_id, dt.tex_text, ac.acr_value, ac.acr_kv_des_id
FROM article_criteria AS ac
JOIN criteria AS c ON ac.acr_cri_id = c.cri_id
JOIN articles AS a ON ac.acr_art_id = a.art_id
JOIN designations AS d ON c.cri_des_id = d.des_id
JOIN des_texts AS dt ON dt.tex_id = d.des_tex_id
JOIN (SELECT distinct la.la_art_id
      FROM link_art AS la
      JOIN link_la_typ AS llt ON la.la_id = llt.lat_la_id
      JOIN (SELECT DISTINCT lgs.lgs_ga_id
            FROM link_ga_str AS lgs
            JOIN search_tree AS st ON lgs.lgs_str_id = st.str_id
            JOIN link_la_typ AS llt ON lgs.lgs_ga_id = llt.lat_ga_id
            WHERE st.str_type = 1
            AND st.str_id = 10132
            AND llt.lat_typ_id = 17484) AS lgs
      ON la.la_ga_id = lgs.lgs_ga_id
      WHERE llt.lat_typ_id = 17484) AS la
ON ac.acr_art_id = la.la_art_id
WHERE a.art_deliverystatus = 1
AND d.des_lng_id = 9
AND c.cri_id = 328
ORDER BY ac.acr_value

所有 IN <subquery>子句可以替换为 JOIN <subquery> ,然后你在哪里JOIN在被测试的列上等于子查询返回的列。和 EXISTS test 转换为与表的连接,将比较移动到子查询的 WHERE 中条款进入ON JOIN 的条款.

可能可以将整个事物展平,而不是通过子查询进行连接。但我怀疑性能会很差,因为这不会减少使用 DISTINCT 的临时表。 .所以你会得到叉积的组合爆炸,然后必须在最后用 DISTINCT 减少它在顶部。

我已将所有隐式连接转换为 ANSI JOIN子句,使结构更清晰,并添加表别名以提高可读性。

关于MySQL 在子子查询中用连接替换 IN 和 EXISTS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27423557/

相关文章:

mysql - 查询Mysql错误: Not unique table/alias

mysql - 在子查询中加入

sql - 如何在内部连接 ​​SQL 中接收特定行

mysql - 为什么我的 MySQL 查询只返回 28 条记录中的 7 条?

php - 从 SQL 数据库获取信息并使用 PHP 显示的问题

mysql - 查询一个人一年内购买了多少次

Mysql Left Join 最后一条记录

sql - 如何使用 Laravel eloquent 在数据透视表上执行额外的内部连接

php - php mysql 未定义索引的问题 - 新学习者需要解释

php - mysql从4个表中选择