0

我有一个查询,它根据所涉及的销售、销售项目和员工构建一行销售信息。它在销售量为 10-20 的开发服务器上运行良好,但在销售量超过 5,000 的终端服务器上运行时,它会使整个系统停止运行。

SELECT Sales.SaleID,
Sales.StaffID,
Sales.CustomerID,
Sales.Timestamp,
Sales.Refunded,
Sales.PaymentType,
Staff.Forename AS staffForename,
Staff.Surname AS staffSurname,
itemList, sumOfCost,
sumOfPrice,
a.sumOfPrice - a.sumOfCost AS sumOfProfit

FROM Sales
INNER JOIN Staff ON Sales.StaffID = Staff.StaffID
LEFT JOIN (
              SELECT SaleID,
              GROUP_CONCAT(Quantity, ' x ', Name) itemList,
              SUM(Cost*Quantity) sumOfCost, SUM(Price*Quantity) sumOfPrice
              FROM SaleItems GROUP BY SaleID
          ) a
ON a.SaleID = Sales.SaleID

WHERE Sales.Deleted = '0'
AND Sales.ShopID = '0'
ORDER BY Sales.Timestamp DESC LIMIT 0,15

任何帮助将不胜感激!此查询的最后一次尝试耗时 65 秒...

4

2 回答 2

0

我只是疯了,还是这正是我需要的?

SELECT Sales.SaleID,
Sales.StaffID, 
Sales.CustomerID, 
Sales.Timestamp, 
Sales.Refunded, 
Sales.PaymentType, 
Staff.Forename AS staffForename, 
Staff.Surname AS staffSurname, 
GROUP_CONCAT(SaleItems.Name) AS ItemList, 
SUM(Cost) AS sumOfCost, 
SUM(Price) AS sumOfCost, 
SUM(Price) - SUM(Cost) AS sumOfProfit 
FROM Sales 
JOIN Staff ON Sales.StaffID = Staff.StaffID 
JOIN SaleItems ON Sales.SaleID = SaleItems.SaleID 
WHERE Sales.Deleted = '0' 
AND Sales.ShopID = '0' 
GROUP BY SaleItems.SaleID 
ORDER BY Sales.Timestamp DESC 
LIMIT 0,15

它似乎给出了正确的结果,但似乎不那么令人费解,因此我以前没有看到它有点令人困惑?

于 2013-01-28T11:22:13.990 回答
0

首先,您没有子查询(在我看来)。对我来说,子查询是一个依赖于查询中另一个表的记录并针对每一行进行处理的查询。您的版本只是一个完整的查询运行一次,获得完整的结果集,然后将其作为连接到其他表的基础。

接下来,您的所有表都应具有其他人在评论中所述的明显索引,例如处理您的所有 JOIN 条件(加入员工 ID、销售 ID 等)。但是,您还应该有一个索引来帮助优化您的 CRITERIA ......在这种情况下,我会有一个索引

(Deleted, ShopID, SaleID )

包含“SaleID”列的原因是用于优化 GROUP BY 和 ORDER BY 子句。看来您只需要最近的 15 次销售。由于时间戳将直接与销售交易相关联,这意味着 SaleID #1 在 SaleID #2 之前有一个时间戳,对于 Sale ID #3、#4、#5 分别以此类推。也就是说,我只需要按销售 ID DESCENDING 完成相同结果的订单。

现在,供您查询。您最初拥有的是一个预查询,它汇总了所有销售、每个项目的各自成本和价格。这可能就是扼杀你的表现的原因。只有这样,您才会丢弃所有不符合您最外层 WHERE 标准的记录。

所以现在你知道我来自哪里,我会做以下事情。我的“PreQuery”不过是从销售表中选择,以获取您的已删除标准和商店 ID 的最近 15 次销售,但按销售 ID 降序排序(与上述示例中的时间戳基本相同)......并且将其限制为 15。然后,完成您的加入和分组,以便您只聚合与 15 个销售相关的行项目,而不是整个销售数据库。由于“PreQuery”已经预先订购了最新的,我们不必重新排序外部结果集。

我确实需要将 group-by 保留在外部级别,因为您可能有 10 个订单项用于单个销售 ID,并且只想显示销售的最终总计条目。

    SELECT 
          S.SaleID,
          S.StaffID,
          S.CustomerID,
          S.Timestamp,
          S.Refunded,
          S.PaymentType,
          Staff.Forename AS staffForename,
          Staff.Surname AS staffSurname,
          GROUP_CONCAT(SI.Quantity, ' x ', SI.Name) itemList,
          SUM(SI.Cost*SI.Quantity) sumOfCost, 
          SUM(SI.Price*SI.Quantity) sumOfPrice,
          SUM(SI.Price*SI.Quantity) - SUM(SI.Cost*SI.Quantity) AS sumOfProfit
       FROM 
          ( select Sales.SaleID
               FROM Sales
               WHERE Sales.Deleted = '0'
                  AND Sales.ShopID = '0'
               ORDER BY 
                  Sales.SaleID DESC 
               LIMIT 
                  0,15 ) PreQuery
             JOIN Sales S
                on PreQuery.SaleID = S.SaleID
                JOIN SaleItems SI
                   ON Sales.SaleID = SI.SaleID
                JOIN Staff 
                   ON S.StaffID = Staff.StaffID
   group by
      S.SaleID
于 2013-01-28T11:46:51.833 回答