2010-01-25 144 views
1

我有一个SQL问题,涉及thisthis问题(但不同)。基本上我想知道如何避免嵌套查询。在这种情况下如何避免嵌套的SQL查询?

比方说,我有一个巨大的工作表(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,我想知道我在这种方法是否是错误的。我应该重写我的查询吗?如何?

回答

2

不,你不应该,你的查询很好。

只需在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摆脱重复的,并会慢得多。

2

您可以通过使用GROUP BY来避免子查询,但如果子查询性能更好,请保留它。

为什么使用LEFT JOIN而不是JOIN加入tools

+0

因为我还没有建立表之间的外键关系。在我这样做后,我可以切换到JOIN,但目前仍可以使用尚未知的工具代码添加到数据库中。我需要这些工作仍然弹出选择。 – thomaspaulb 2010-01-25 14:47:22

相关问题