2017-10-16 214 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更优化。