查询优化。重复的子查询

时间:2016-08-11 15:58:46

标签: sql sql-server sql-server-2005 query-optimization

我们在遗留系统中发现了一个慢查询。我在查询中看到的是一个重复的片段。这是完整的查询:

DECLARE @SellerId INT;
DECLARE @DateFrom DATETIME;
DECLARE @DateTo DATETIME;

SET @SellerId = 5396884;
SET @DateFrom = '2016-01-05';
SET @DateTo = '2016-10-08';

DECLARE @CurrentDate DATETIME;
SET @CurrentDate = GETDATE();



CREATE TABLE #ReportDate (codes INT, dates DATETIME);
DECLARE @dif as INT;
DECLARE @cont as INT;
DECLARE @currdate as DATETIME;
SET @dif = DATEDIFF(day, @DateFrom, @DateTo);
SET @cont = 1;
SET @currdate = @DateFrom - 1;
WHILE (@cont <= @dif + 1)
BEGIN
    SET @currdate = DATEADD(DAY, 1, @currdate);
    INSERT INTO #ReportDate VALUES (@cont, @currdate);
    SET @cont = @cont + 1;
END


/* HOW TO OPTIMIZE THIS ONE? */
SELECT
        #ReportDate.dates as valid_date,
        (
          SELECT 

          COUNT(DISTINCT(nonCancelledSales.num_remito)) as actives

          FROM      
                (

                    SELECT *

                    FROM salesView

                    WHERE

                        salesView.sell_id NOT IN 
                            (
                              SELECT sell_id

                              FROM salesStates

                              WHERE
                                  salesStates.aborted = 1
                            ) 

                  ) nonCancelledSales

          WHERE
                nonCancelledSales.seller_id = @SellerId AND
                nonCancelledSales.cancelled = 0 AND
                nonCancelledSales.void = 0 AND
                nonCancelledSales.hasDiscount = 0 AND
                nonCancelledSales.dateOfSale <=  #ReportDate.dates AND
                nonCancelledSales.currentState =  (SELECT   MAX(hveest.date)

                                              FROM  salesStates hveest

                                              WHERE 
                                                    hveest.sell_id = nonCancelledSales.sell_id AND
                                                    hveest.date <= #ReportDate.dates) AND
                nonCancelledSales.lastProductDate = (SELECT     MAX(hvepro.date)

                                              FROM  productHistory hvepro

                                              WHERE 
                                                    hvepro.sell_id = nonCancelledSales.sell_id AND
                                                    hvepro.date <= #ReportDate.dates) 

        ) total_actives,

        (
          SELECT 

          ISNULL(SUM(nonCancelledSales.paymentValue),0) as active

          FROM      
                (

                    SELECT *

                    FROM salesView

                    WHERE

                        salesView.sell_id NOT IN 
                            (
                              SELECT sell_id

                              FROM salesStates

                              WHERE
                                  salesStates.aborted = 1
                            ) 

                  ) nonCancelledSales

          WHERE
                nonCancelledSales.seller_id = @SellerId AND
                nonCancelledSales.cancelled = 0 AND
                nonCancelledSales.void = 0 AND
                nonCancelledSales.hasDiscount = 0 AND
                nonCancelledSales.dateOfSale <=  #ReportDate.dates AND
                nonCancelledSales.currentState =  (SELECT   MAX(hveest.date)

                                              FROM  salesStates hveest

                                              WHERE 
                                                    hveest.sell_id = nonCancelledSales.sell_id AND
                                                    hveest.date <= #ReportDate.dates) AND
                nonCancelledSales.lastProductDate = (SELECT     MAX(hvepro.date)

                                              FROM  productHistory hvepro

                                              WHERE 
                                                    hvepro.sell_id = nonCancelledSales.sell_id AND
                                                    hvepro.date <= #ReportDate.dates)             
        ) active
FROM 
        #ReportDate
GROUP BY
        #ReportDate.dates



DROP TABLE #ReportDate

以下是我看到的两个重复片段:

(
          SELECT 

          COUNT(DISTINCT(nonCancelledSales.num_remito)) as actives

          FROM      
                (

                    SELECT *

                    FROM salesView

                    WHERE

                        salesView.sell_id NOT IN 
                            (
                              SELECT sell_id

                              FROM salesStates

                              WHERE
                                  salesStates.aborted = 1
                            ) 

                  ) nonCancelledSales

          WHERE
                nonCancelledSales.seller_id = @SellerId AND
                nonCancelledSales.cancelled = 0 AND
                nonCancelledSales.void = 0 AND
                nonCancelledSales.hasDiscount = 0 AND
                nonCancelledSales.dateOfSale <=  #ReportDate.dates AND
                nonCancelledSales.currentState =  (SELECT   MAX(hveest.date)

                                              FROM  salesStates hveest

                                              WHERE 
                                                    hveest.sell_id = nonCancelledSales.sell_id AND
                                                    hveest.date <= #ReportDate.dates) AND
                nonCancelledSales.lastProductDate = (SELECT     MAX(hvepro.date)

                                              FROM  productHistory hvepro

                                              WHERE 
                                                    hvepro.sell_id = nonCancelledSales.sell_id AND
                                                    hvepro.date <= #ReportDate.dates) 

        ) total_actives,

        (
          SELECT 

          ISNULL(SUM(nonCancelledSales.paymentValue),0) as active

          FROM      
                (

                    SELECT *

                    FROM salesView

                    WHERE

                        salesView.sell_id NOT IN 
                            (
                              SELECT sell_id

                              FROM salesStates

                              WHERE
                                  salesStates.aborted = 1
                            ) 

                  ) nonCancelledSales

          WHERE
                nonCancelledSales.seller_id = @SellerId AND
                nonCancelledSales.cancelled = 0 AND
                nonCancelledSales.void = 0 AND
                nonCancelledSales.hasDiscount = 0 AND
                nonCancelledSales.dateOfSale <=  #ReportDate.dates AND
                nonCancelledSales.currentState =  (SELECT   MAX(hveest.date)

                                              FROM  salesStates hveest

                                              WHERE 
                                                    hveest.sell_id = nonCancelledSales.sell_id AND
                                                    hveest.date <= #ReportDate.dates) AND
                nonCancelledSales.lastProductDate = (SELECT     MAX(hvepro.date)

                                              FROM  productHistory hvepro

                                              WHERE 
                                                    hvepro.sell_id = nonCancelledSales.sell_id AND
                                                    hvepro.date <= #ReportDate.dates)             
        ) active

是否完全有必要复制查询?在他得到的第一个:

 COUNT(DISTINCT(nonCancelledSales.num_remito)) as actives

在第二个:

  ISNULL(SUM(nonCancelledSales.paymentValue),0) as active

我想必须有一些方法来重写查询,但我不确定如何。

1 个答案:

答案 0 :(得分:0)

如果您使用OUTER APPLY,则可以将这些组合在一起。

这个想法是:

SELECT . . ., x.actives, x.active
FROM #ReportDate OUTER APPLY
     (SELECT COUNT(DISTINCT(nonCancelledSales.num_remito)) as actives, 
             COALESCE(SUM(nonCancelledSales.paymentValue), 0) as active
      . . . -- rest of query here
     ) x;

在这种情况下,OUTER APPLY很像FROM子句中可以返回多行的相关子查询。