1

I have an SQL question, related to this and this question (but different). Basically I want to know how I can avoid a nested query.

Let's say I have a huge table of jobs (jobs) executed by a company in their history. These jobs are characterized by year, month, location and the code belonging to the tool used for the job. Additionally I have a table of tools (tools), translating tool codes to tool descriptions and further data about the tool. Now they want a website where they can select year, month, location and tool using a dropdown box, after which the matching jobs will be displayed. I want to fill the last dropdown with only the relevant tools matching the before selection of year, month and location, so I write the following nested query:

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

I resorted to this nested query because it was much faster than performing a JOIN on the complete database and selecting from that. It got my query time down a lot. But as I have recently read that MySQL nested queries should be avoided at all cost, I am wondering whether I am wrong in this approach. Should I rewrite my query differently? And how?

4

2 回答 2

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摆脱重复,并且会慢得多。

于 2010-01-25T14:34:47.823 回答
2

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

为什么你使用 aLEFT JOIN而不是 aJOIN加入tools

于 2010-01-25T14:36:55.970 回答