sql - 在这种情况下如何避免嵌套的 SQL 查询?

标签 sql mysql subquery

我有一个与 this 相关的 SQL 问题和 this问题(但不同)。基本上我想知道如何避免嵌套查询。

假设我有一个巨大的工作表(jobs),由一家公司在其历史上执行过。这些工作的特点是年、月、地点和属于该工作所用工具的代码。此外,我还有一个工具表 (tools),将工具代码转换为工具描述和有关该工具的更多数据。现在他们想要一个网站,他们可以在其中使用下拉框选择年、月、地点和工具,之后将显示匹配的工作。我只想用与之前选择的年、月和位置相匹配的相关工具来填充最后一个下拉列表,因此我编写了以下嵌套查询:

SELECT c.tool_code, t.tool_description
FROM (
 SELECT DISTINCT j.tool_code
 FROM jobs AS j
 WHERE j.year = ....
        AND j.month = ....
 AND j.location = ....
) AS c
LEFT JOIN tools as t
ON c.tool_code = t.tool_code
ORDER BY c.tool_code ASC

我求助于这个嵌套查询,因为它比在整个数据库上执行 JOIN 并从中进行选择要快得多。它让我的查询时间减少了很多。但正如我最近读到的那样MySQL nested queries should be avoided at all cost ,我想知道我这种方法是否错误。我应该以不同的方式重写我的查询吗?以及如何?

最佳答案

不,你不应该,你的查询没问题。

只需在 jobs (year, month, location, tool_code)tools (tool_code) 上创建一个索引,以便 INDEX FOR GROUP-BY可以使用。

您提供的文章描述的是子查询谓词 (IN (SELECT ...)),而不是嵌套查询 (SELECT FROM (SELECT ...))。

即使有子查询,这篇文章也是错误的:虽然 MySQL 不能优化所有子查询,但它处理 IN (SELECT …) 谓词就好了。

不知道作者为什么选择把DISTINCT放在这里:

SELECT  id, name, price
FROM    widgets
WHERE   id IN
        (
        SELECT  DISTINCT widgetId
        FROM    widgetOrders
        )

为什么他们认为这将有助于提高性能,但考虑到 widgetID 已建立索引,MySQL 只会转换此查询:

SELECT  id, name, price
FROM    widgets
WHERE   id IN
        (
        SELECT  widgetId
        FROM    widgetOrders
        )

进入index_subquery

本质上,这就像 EXISTS 子句:内部子查询将在每个 widgets 行执行一次,并添加额外的谓词:

SELECT  NULL
FROM    widgetOrders
WHERE   widgetId = widgets.id

并在 widgetOrders 中的第一个匹配处停止。

这个查询:

SELECT  DISTINCT w.id,w.name,w.price
FROM    widgets w
INNER JOIN
        widgetOrders o
ON      w.id = o.widgetId

将不得不使用 temporary 来删除重复项,而且速度会慢得多。

关于sql - 在这种情况下如何避免嵌套的 SQL 查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2132905/

相关文章:

sql - 计算两个时间戳之间的差异时出现ORA-01873

sql - 数据库如何实现 SQL 'ORDER BY x' ?

mysql - 使用子查询上的左连接和最大值来加速 mysql 查询

sql - 相关子查询如何与 Exists 运算符一起使用?

mysql - 使用 ON DUPLICATE KEY 将列增加一定数量 MySQL NodeJS

mysql - 查询获取带有子记录的父记录,然后是mysql中的下一个父子记录

php - 显示上次插入数据的数据时出现问题

PHP MySQL 查询提交按钮

php - 验证帐户状态

mysql - 分组后选择中的子查询