2013-01-23 43 views
1

我有三個表,products,variantsdataMySQL查詢:當使用ifnull連接表時響應慢

每個產品都有自己的productcode。產品可以有任何數量的變體,包括無。變體有自己的代碼variantcode。產品列有productid列,每個變體都有相關的productid列。

我想要一個所有代碼的列表,但如果產品沒有變體,我只關心productcode。否則,我想要variantcode。我寫了這個查詢來得到這個列表:

SELECT IFNULL(variants.variantcode, products.productcode) AS code 
FROM products 
LEFT OUTER JOIN variants ON (products.productid = variants.productid) 
ORDER BY code 

這個查詢按我的預期工作。

data表包含每個代碼的額外數據。我想將這些數據加入到這個列表中。我想這個查詢:

SELECT IFNULL(variants.variantcode, products.productcode) AS code 
FROM products 
LEFT OUTER JOIN variants ON (products.productid = variants.productid) 
LEFT OUTER JOIN data ON (data.partno = code) 
ORDER BY code 

但我「在‘關於條款’未知列‘代碼’」得到一個錯誤。我以爲這已經是與code是一個生成的值,所以後來我嘗試此查詢:

SELECT IFNULL(variants.variantcode, products.productcode) AS code 
FROM products 
LEFT OUTER JOIN variants ON (products.productid = variants.productid) 
LEFT OUTER JOIN data ON (data.partno = IFNULL(variants.variantcode, products.productcode)) 
ORDER BY code 

這個查詢工作,但花了很長時間(〜20秒VS < 1秒第一個查詢) 。 ON子句中的IFNULL是否是問題?我如何加快速度?

+0

你需要使用一個派生查詢此。 – Kermit

回答

1

試試這個:

select product_variants.code from 

(SELECT IFNULL(variants.variantcode, products.productcode) AS code 
FROM products 
LEFT OUTER JOIN variants ON (products.productid = variants.productid) 
ORDER BY code) 

as product_variants 

LEFT OUTER JOIN data ON (data.partno = product_variants.code) 
+0

這個伎倆!張貼在此之後我看着衍生查詢所推薦的@njk,寫下這樣的查詢: 'SELECT product_variants.code FROM (SELECT IFNULL(variants.variantcode,products.productcode)AS代碼 從產品 LEFT OUTER JOIN變異體(products.productid = variants.productid)) AS product_variants LEFT OUTER JOIN ON(data.partno = product_variants.code) ORDER BY數據product_variants.code' 其中的工作,但仍了20秒。爲什麼移動ORDER BY加快速度? – pjgat09

+1

您可以通過在查詢前添加'EXPLAIN'關鍵字來檢查執行計劃如何受到影響,例如'EXPLAIN select product_variants.code ...'它會顯示是否使用了索引以及返回的估計行數。 –

+0

感謝@Adrian的建議。我花了一點時間看看EXPLAIN,並沒有在'data'上使用任何索引。我嘗試修改索引,但沒有使用。使用與「productcode」和「variantcode」不同的排序規則來表示'partno'字段。這是因爲我在做桌時出現了錯誤。我改變了排序來匹配,現在我的查詢運行得很快。 – pjgat09

0

有一件事你可以嘗試是加入到你的data表兩次,這樣的事情:

SELECT IFNULL(variants.variantcode, products.productcode) AS code 
    , IFNULL(D1.something, D2.something) AS something 
FROM products 
LEFT OUTER JOIN variants 
ON (products.productid = variants.productid) 
LEFT OUTER JOIN data as D1 
ON (D1.partno = variants.variantcode) 
LEFT OUTER JOIN data as D2 
ON (D2.partno = products.productcode) 
ORDER BY code 
+0

這似乎會工作,但不會需要'數據'中的每一列IFNULL? – pjgat09

+0

是的,從你的問題中不清楚你需要'data'中的所有列。使用上面的派生表可能是最好的;我只是表現出不同的方式。 – BellevueBob

+0

啊,好的。我的頭腦中有一個類似這樣的想法,所以很高興看到它寫出來。謝謝! – pjgat09