sql - 我可以强制mysql先执行子查询吗?

标签 sql mysql subquery

我有这样的查询:

SELECT `table_1`.* from `table_1`
  INNER JOIN `table_2` [...]
  INNER JOIN `table_3` [...]
WHERE `table_1`.`id` IN(
  SELECT `id` FROM [...]
)
AND [more conditions]

当我使用 EXPLAIN 时,末尾有'DEPENDENT SUBQUERY',但我希望在其他条件之前先执行此子查询。

有可能吗?

最佳答案

SELECT  `table_1`.*
FROM    `table_1`
INNER JOIN
        `table_2` [...]
INNER JOIN
        `table_3` [...]
WHERE   `table_1`.`id` IN
        (
        SELECT  `id`
        FROM    [...]
        )
        AND [more conditions]

如果内表被正确索引,严格意义上来说,这里的子查询根本就没有被“执行”。

由于子查询是 IN 表达式的一部分,因此条件被插入子查询并将其转换为 EXISTS

事实上,这个子查询在每一步都被评估:

EXISTS
(
SELECT  NULL
FROM    [...]
WHERE   id = table1.id
)

您实际上可以在EXPLAIN EXTENDED 提供的详细说明中看到它。

这就是它被称为DEPENDENT SUBQUERY 的原因:每次求值的结果取决于table1.id 的值。子查询本身不相关,相关的是优化版本。

MySQL 总是在更简单的过滤器之后评估 EXISTS 子句(因为它们更容易评估,并且子查询有可能不会在全部)。

如果您希望子查询一次全部求值,请将查询重写为:

SELECT  table_1.*
FROM    (
        SELECT  DISTINCT id
        FROM    [...]
        ) q
JOIN    table_1
ON      table_1.id = q.id
JOIN    table_2
ON      [...]
JOIN    table_3
ON      [...]
WHERE   [more conditions]

这会强制子查询在连接中处于领先地位,如果子查询比 table_1 小,则效率更高,如果子查询比 table_1.

如果在子查询中使用了 [...].id 上的索引,则子查询将使用 INDEX FOR GROUP-BY 执行。

关于sql - 我可以强制mysql先执行子查询吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1766702/

相关文章:

php - 转换表ascii php中的特殊字符

php - 为每个月 mysql 选择一行

mysql - 使用mysql查询获取基于语言的详细信息?

MySQL 与字符串相交?

php - 如何将 ZF ->joinLeft()s 变成子查询?

sql - 如何在不列出列的情况下对每一列执行相同的聚合?

sql - 如果列的值匹配,则删除与特定 ID 对应的所有行

php - 带有指向另一个表中行的链接的 SQL 表

php - 复杂的 MySQL 查询 : solution to work with views (datatables. ..)

MySQL 标记系统 - 每月热门关键词