查询优化,(子查询)(sql-transact)

时间:2014-02-13 20:26:39

标签: sql query-optimization having subquery

这是我必须优化的代码,我设法只使用索引并为SUBSTRING语句更改LIKE,将其降低到起始成本的一半。我现在的问题是最后一行中的子查询,以及select中的SUM行,我相信我必须通过创建一个新的表或列来摆脱它们,但是无法完成它。

SELECT 
C.LastName as Customer , e.LastName as SalesPerson, s.ProductID,
p.Name as ProductName, SUM( s.Quantity ) as quantity, 
SUM ( p.Price * s.Quantity ) as amount 
FROM dbo.Sales s, dbo.Customers c, dbo.Employees e, dbo.Products p 
WHERE 
 s.CustomerID = c.CustomerID and 
 s.ProductID = p.ProductID and 
 s.SalesPersonID = e.EmployeeID and
 p.Name like 'Paint%' 
GROUP BY C.LastName , e.LastName , s.ProductID, p.Name 
HAVING sum ( s.Quantity ) < 
(select AVG(s2.Quantity) from dbo.Sales s2 where s2.ProductID=s.ProductID ) 

欢迎任何帮助,提前谢谢。

3 个答案:

答案 0 :(得分:0)

如果使用SQL Server,您可以使用窗口函数简化这一点:

WITH cte AS (   SELECT  C.LastName AS Customer
                      , e.LastName AS SalesPerson
                      , s.ProductID
                      , p.Name AS ProductName
                      , SUM(s.Quantity) AS quantity
                      , SUM(p.Price * s.Quantity) AS amount
                      , SUM(SUM(s.Quantity)) OVER (PARTITION BY s.ProductID)*1.0/SUM(COUNT(*)) OVER (PARTITION BY s.ProductID) AS Avg_Qty
                FROM     dbo.Sales s
                    JOIN dbo.Customers c ON s.CustomerID = c.CustomerID
                    JOIN dbo.Employees e ON s.SalesPersonID = e.EmployeeID
                    JOIN dbo.Products p ON s.ProductID = p.ProductID
                WHERE   s.Name LIKE 'Paint%'
                GROUP BY C.LastName
                      , e.LastName
                      , s.ProductID
                      , p.Name
            )
SELECT * 
FROM  cte
WHERE quantity < Avg_Qty

添加Name_Category字段或类似字段以避免使用LIKE会有所帮助。

答案 1 :(得分:0)

目前无法测试,但我认为这应该有效:

SELECT c.LastName as Customer , 
       e.LastName as SalesPerson, 
       s.ProductID,
       p.Name as ProductName, 
       SUM(s.Quantity) as quantity, 
       SUM(p.Price * s.Quantity) as amount 
  FROM dbo.Sales s, 
  JOIN dbo.Customers c
    ON c.CustomerID = s.CustomerID 
  JOIN dbo.Employees e
    ON e.EmployeeID = s.SalesPersonID
  JOIN dbo.Products p 
    ON p.ProductID = s.ProductID
   AND p.Name like 'Paint%'
  JOIN (SELECT ProductID,
               AVG(Quantity) as avg_Quantity
          FROM dbo.Sales) s2 
    ON s2.ProductID = s.ProductID
 GROUP BY c.LastName , e.LastName , s.ProductID, p.Name 
HAVING sum(s.Quantity) <  AVG(s2.avg_Quantity) 

答案 2 :(得分:0)

这与您的陈述相同,但速度更快:

SELECT 
C.LastName as Customer , e.LastName as SalesPerson, s.ProductID,
p.Name as ProductName, SUM( s.Quantity ) as quantity, 
SUM ( p.Price * s.Quantity ) as amount 
FROM dbo.Sales s
INNER JOIN dbo.Products p ON s.ProductID = p.ProductID /*AND p.Name like 'Paint%' --optionally place filter here if you like*/
INNER JOIN (SELECT s2.ProductID SalesProductID, AVG(s2.Quantity)AVG_Quantity FROM dbo.Sales s2 GROUP BY s2.ProductID)ProductSales ON ProductSales.SalesProductID = s.ProductID
INNER JOIN dbo.Customers c ON s.CustomerID = c.CustomerID
INNER JOIN dbo.Employees e ON s.SalesPersonID = e.EmployeeID
WHERE p.Name like 'Paint%' 
GROUP BY C.LastName , e.LastName , s.ProductID, p.Name