2012-07-26 78 views
0

我有做工精細的查詢,但它有2個相同的子查詢MySQL:如何使用兩個有意義的子查詢來優化查詢?

SELECT *, 
    (SELECT count(O.id) FROM `offer` O WHERE O.product_id = P.id) AS poffers 
FROM `product` P 
JOIN product_section PS ON (PS.product_id = P.id AND PS.section_id IN (14)) 
WHERE P.deleted is NULL 
    AND (SELECT count(O.id) FROM `offer` O WHERE O.product_id = P.id) > 0 

我嘗試用JOIN優化,但新的查詢返回空結果

SELECT *, OJ.pcount AS poffers 
FROM `product` P 
JOIN product_section PS ON PS.product_id = P.id AND PS.section_id IN (14) 
JOIN (SELECT count(O.id) AS pcount, O.product_id FROM `offer` O) 
    AS OJ ON OJ.product_id = P.id 
WHERE P.deleted is NULL AND OJ.pcount > 0 

比我嘗試變數,但我想我用錯了,查詢返回空結果

SELECT *, 
    @o := (SELECT count(O.id) FROM `offer` O WHERE O.product_id = P.id) 
    AS poffers 
FROM `product` P 
JOIN product_section PS ON (PS.product_id = P.id AND PS.section_id IN (14)) 
WHERE P.deleted is NULL 
    AND @o > 0 
+0

你有一些示例數據嗎?也許你可以在[sqlfiddle](http://sqlfiddle.com/)上設置一個小例子? – MvG 2012-07-26 16:19:04

+0

如何添加一些數據? – deerua 2012-07-26 16:25:15

+1

嘗試將GROUP BY product_id添加到您的1-st優化嘗試的子查詢中。 – Vatev 2012-07-26 16:26:48

回答

1

避免相關子查詢。相反,有一個與產品相關的查詢提供計數。這個查詢可以在幾個地方使用。它很可能會暫時存儲在內存中,避免重複計算,但數據庫引擎也可能會做更聰明的事情。

SELECT *, O.cnt AS poffers 
FROM product P 
JOIN product_section PS ON (PS.product_id = P.id AND PS.section_id IN (14)) 
JOIN (SELECT product_id, count(id) AS cnt 
     FROM offer 
     GROUP BY product_id 
    ) O ON (O.product_id = P.id) 
WHERE P.deleted is NULL AND O.cnt > 0 

如果P和PS之間的關係是一個對一個,那麼你甚至可以不用任何subquerys工作:

SELECT *, COUNT(O.id) AS poffers 
FROM product P 
JOIN product_section PS ON (PS.product_id = P.id AND PS.section_id IN (14)) 
JOIN offer O ON (O.product_id = P.id) 
WHERE P.deleted is NULL 
GROUP BY P.id 

你也應該考慮是否有一個很好的理由來算一個特定的列。在大多數情況下,COUNT(*)將比COUNT(col)更快。使用後者的唯一原因是,如果您明確希望從計數中排除NULL值。

+0

空結果:) – deerua 2012-07-26 16:15:11

+0

這個查詢與我的查詢#2的邏輯相同 – deerua 2012-07-26 16:17:28

+0

您的第二個查詢就像diEcho,而且它非常慢 – deerua 2012-07-26 16:19:17

1

試試看(未測試)

SELECT P.*,PS.*,count(O.id) AS oCount 
FROM `product` P 
INNER JOIN `product_section` PS ON (PS.product_id = P.id) 
INNER JOIN `offer` O ON (O.product_id = P.id) 
WHERE P.deleted is NULL AND PS.section_id =14 
GROUP BY O.product_id 
HAVING oCount> 0 

更優化

SELECT P.*,PS.*,count(O.id) AS oCount 
FROM `product` P 
INNER JOIN (`product_section` PS,`offer` O) ON 
(PS.product_id = P.id AND O.product_id = P.id) 
WHERE P.deleted is NULL AND PS.section_id =14 
GROUP BY O.product_id 
HAVING oCount> 0 

TIPS:

  • 不使用*,而不是隻寫要在其上使用的所有列檢索
  • 賺指數的列名與ON & WHERE條件

Reference

+0

其返回1條目 - 必須返回2 – deerua 2012-07-26 15:40:30

+0

和oCount返回8 = 2條目的總和 – deerua 2012-07-26 15:41:07

+0

好,你修好了:) – deerua 2012-07-26 15:42:09