2017-10-16 156 views
1

我有一個查詢,顯示每個產品的銷售數量,小計和總銷售額的總和。問題是執行時間太長。我做錯了嗎?我需要你的幫助來優化查詢。另外,我應該由sd.Product_Id或p.Product_Name分組嗎?優化計算小計,折扣和每個產品的總計的SQL查詢

SELECT p.Product_Name `Product Name`, 
     SUM(sd.Quantity) `Quantity Sold`, 
     SUM(sd.Subtotal) `Subtotal`, 
     SUM(sd.Discount_Value) `Total Discount`, 
     SUM(sd.Total) `Total` 
FROM Sales_Detail sd 
JOIN Product p ON sd.Product_Id = p.Id 
WHERE DATE(sd.Purchase_Date) BETWEEN DATE('2017-08-21') 
           and date('2017-08-25') 
GROUP BY p.Product_Name; 
+1

如果'DATE(sd.Purchase_Date)'正在轉換日期時間字段停止這樣做。在操作數之間指定也是日期時間類型。 – Hogan

+0

你應該發佈它作爲答案,而不僅僅是一個評論。我原來的查詢是200+秒。現在降到3秒!謝謝! –

+0

但是返回的原始行是1091.修改後的查詢只返回973.我仍然需要檢查哪些行被刪除 –

回答

2

確保您對Sales_Detail.Purchase_Date列的索引,然後重寫查詢以去除環境該列的功能,因此它可以利用指數的優勢:

SELECT p.Product_Name `Product Name`, 
    SUM(sd.Quantity) `Quantity Sold`, 
    SUM(sd.Subtotal) `Subtotal`, 
    SUM(sd.Discount_Value) `Total Discount`, 
    SUM(sd.Total) `Total` 
FROM Sales_Detail sd 
JOIN Product p ON sd.Product_Id = p.Id 
WHERE sd.Purchase_Date >= '2017-08-21' 
    AND sd.Purchase_Date < '2017-08-26' 
GROUP BY p.Product_Name; 
+0

感謝您的幫助!只是一個noob問題,我應該擔心沒有00:00:00在哪裏聲明的日期? –

+0

如果'Purchase_Date'是'DATE',那麼您已經排除了整個第一天。 –

+1

@HarambeAttackHelicopter - 日期時間字面值可以有或沒有00:00:00 - 它沒有區別。即使與'DATE'或'DATETIME'相比。 –

0

sd需求INDEX(Purchase_Date)改寫:

WHERE sd.Purchase_Date >= '2017-08-21' 
     sd.Purchase_Date < '2017-08-26' -- next day 

這適用於任何味道的日期/ dat ETIME /等。

這可能會更好,因爲它避免了計算leapyears等:

WHERE sd.Purchase_Date >= '2017-08-21' 
     sd.Purchase_Date < '2017-08-21' + INTERVAL 5 DAY 

另外,考慮改變GROUP BY

GROUP BY sd.Product_Id 

,因爲它應該是相同的。而且,當時,有

INDEX(Purchase_Date, Product_Id) 

這將是「覆蓋」並很可能會通過與指數(而不是隨後的「文件排序」)處理GROUP BY更優化。