【问题标题】:Need to speed up this SQL query需要加速这个 SQL 查询
【发布时间】:2013-06-22 01:47:29
【问题描述】:

我的查询结构如下:

SELECT DISTINCT (CO.CateringOrderId),
               CO.CateringOrderNumber,
               MC.FirstName + ' ' + MC.LastName AS "CustomerName",
               CO.EventDate AS EventDate,
               CO.IsCompleted,
               CO.IsVerified,
               MC.EmailId,
               CAT.OfficePhone,
               CAT.Mobile,
               CAT.Fax,
               CO.TotalInvoiceAmount,
               CO.BarterCharityId,
               (SELECT Sum (Amount)
                FROM Catering_Order_Payment_Trans
                WHERE CateringOrderId = CO.CateringOrderId) AS AmountReceived
 FROM Catering_Orders CO,
      Master_Customer MC,
      Customer_Address_Trans CAT,
      Catering_Order_Employee_Trans COET
WHERE  MC.CompanyId = @p_CompanyId
  AND (MC.CustomerId = @p_CustomerId OR @p_CustomerId = -1)
  AND (CO.CateringOrderNumber LIKE '%' + @p_CateringOrderNumber + '%')
  AND (CO.EventDate >= CONVERT (DATETIME, @p_FromDate) OR @p_FromDate = '')
  AND (CO.EventDate <= CONVERT (DATETIME, @p_ToDate) OR @p_ToDate = '')
  AND (CO.IsCompleted = @p_IsCompleted OR @p_IsCompleted = -1)
  AND (COET.EmployeeId = @p_CatererId OR @p_CatererId = -1)
  AND MC.CustomerId = CO.CustomerId
  AND MC.PersonalAddressId = CAT.CustomerAddressId
  AND (COET.CateringOrderId = CO.CateringOrderId
       OR CO.CateringOrderId NOT IN
          (SELECT CateringOrderId FROM Catering_Order_Employee_Trans))
  AND (CAT.Mobile like '%' + @p_ContactNumber + '%' ) 
  AND (CO.IsActive is null or CO.IsActive=1)
ORDER BY CO.CateringOrderId DESC

我认为SUM 子查询会减慢它的速度。请建议我如何加快速度。 目前它的执行时间约为 7 - 10 秒。

【问题讨论】:

  • 执行计划是什么样的? SQL Server 应该能够将该查询去关联到左外连接。
  • 请提供完整的查询示例。
  • @Devart 我已经更新了问题
  • DISTINCT 隐藏了不正确的JOIN 条件吗? COET.CateringOrderId = CO.CateringOrderId OR CO.CateringOrderId NOT IN ... 在我看来很可疑。也请考虑使用ANSI 92 JOIN 关键字。这样可以更轻松地查看您是否有任何无意的交叉连接。
  • @MartinSmith 谢谢让我看看

标签: sql sql-server subquery query-optimization


【解决方案1】:

试试这样的 -

SELECT DISTINCT 
    CO.CateringOrderId,
    CO.CateringOrderNumber,
    MC.FirstName + ' ' + MC.LastName AS CustomerName,
    CO.EventDate AS EventDate,
    CO.IsCompleted,
    CO.IsVerified,
    MC.EmailId,
    CAT.OfficePhone,
    CAT.Mobile,
    CAT.Fax,
    CO.TotalInvoiceAmount,
    CO.BarterCharityId,
    AmountReceived = (
        SELECT SUM(t.Amount)
        FROM dbo.Catering_Order_Payment_Trans t
        WHERE t.CateringOrderId = CO.CateringOrderId
    )
FROM (
    SELECT *
    FROM dbo.Catering_Orders
    WHERE ISNULL(IsActive, 1) = 1
        AND (IsCompleted = @p_IsCompleted OR @p_IsCompleted = -1)
        AND CateringOrderNumber LIKE '%' + @p_CateringOrderNumber + '%'
        AND EventDate BETWEEN 
            CONVERT(DATETIME, ISNULL(NULLIF(@p_FromDate, ''), '18000101'))
            AND 
            CONVERT(DATETIME, ISNULL(NULLIF(@p_ToDate, ''), '30000101'))
) CO
JOIN dbo.Master_Customer MC ON MC.CustomerId = CO.CustomerId
JOIN dbo.Customer_Address_Trans CAT ON MC.PersonalAddressId = CAT.CustomerAddressId
LEFT JOIN (
    SELECT *
    FROM dbo.Catering_Order_Employee_Trans
    WHERE EmployeeId = @p_CatererId 
        OR @p_CatererId = -1
) COET ON COET.CateringOrderId = CO.CateringOrderId
WHERE MC.CompanyId = @p_CompanyId
    AND (MC.CustomerId = @p_CustomerId OR @p_CustomerId = -1)
    AND CAT.Mobile LIKE '%' + @p_ContactNumber + '%' 

主要问题

AND (COET.CateringOrderId = CO.CateringOrderId
       OR CO.CateringOrderId NOT IN
          (SELECT CateringOrderId FROM Catering_Order_Employee_Trans))

 (SELECT Sum (Amount)
                FROM Catering_Order_Payment_Trans
                WHERE CateringOrderId = CO.CateringOrderId) AS AmountReceived

【讨论】:

    【解决方案2】:

    试试:

    SELECT CO.CateringOrderId,
           CO.CateringOrderNumber,
           MC.FirstName + ' ' + MC.LastName AS "CustomerName",
           CO.EventDate AS EventDate,
           CO.IsCompleted,
           CO.IsVerified,
           MC.EmailId,
           CAT.OfficePhone,
           CAT.Mobile,
           CAT.Fax,
           CO.TotalInvoiceAmount,
           CO.BarterCharityId,
           COPT.AmountReceived
    FROM Catering_Orders CO
    JOIN Master_Customer MC ON MC.CustomerId = CO.CustomerId
    JOIN Customer_Address_Trans CAT ON MC.PersonalAddressId = CAT.CustomerAddressId
    LEFT JOIN (SELECT CateringOrderId, Sum(Amount) AS AmountReceived
               FROM Catering_Order_Payment_Trans
               GROUP BY CateringOrderId) COPT
      ON COPT.CateringOrderId = CO.CateringOrderId
    WHERE  MC.CompanyId = @p_CompanyId
      AND (MC.CustomerId = @p_CustomerId OR @p_CustomerId = -1)
      AND (CO.CateringOrderNumber LIKE '%' + @p_CateringOrderNumber + '%')
      AND (CO.EventDate >= CONVERT (DATETIME, @p_FromDate) OR @p_FromDate = '')
      AND (CO.EventDate <= CONVERT (DATETIME, @p_ToDate) OR @p_ToDate = '')
      AND (CO.IsCompleted = @p_IsCompleted OR @p_IsCompleted = -1)
      AND EXISTS
          (SELECT NULL 
           FROM Catering_Order_Employee_Trans COET 
           WHERE COET.CateringOrderId = CO.CateringOrderId AND 
                 (COET.EmployeeId = @p_CatererId OR @p_CatererId = -1) )
      AND (CAT.Mobile like '%' + @p_ContactNumber + '%' ) 
      AND (CO.IsActive is null or CO.IsActive=1)
    ORDER BY CO.CateringOrderId DESC
    

    【讨论】:

      【解决方案3】:

      要优化您的查询,您应该编辑插入在 AND 条件中的 OR 条件,这确实会减慢您的查询速度

      AND (   CO.EventDate <= CONVERT (DATETIME, @p_ToDate)
             OR @p_ToDate = '')
      

      应该变成类似

       AND (   CO.EventDate <= CASE WHEN @p_ToDate = '' THEN 
                              GETDATE() 
                          ELSE 
                              CONVERT (DATETIME,@p_ToDate) 
                          END)
      

      还尝试在 select 和 where 中逐一删除嵌套的 select 以查看哪个最会减慢查询速度

      【讨论】:

      • 谢谢..我可以用 SUM 子查询做什么?
      • 您可以在join中添加该表,在select中您将直接进行求和,然后将group by子句与其他列一起添加
      猜你喜欢
      • 2015-04-07
      • 2020-01-30
      • 2016-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-23
      • 2021-06-28
      • 2011-04-25
      相关资源
      最近更新 更多