2010-01-25 176 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

相關問題