2016-08-11 9 views
0

従来のシステムでは低速なクエリが見つかりました。私がクエリーで見るものは、重複フラグメントです。ここでは、完全なクエリがあります:ここではクエリの最適化。重複したサブクエリ

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 

は、私が見る2つの重複断片である:

(
      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 

私は、クエリを書き換えるためにいくつかの方法があるように持っていると私はどのようにわかりません。

+0

は一度に1つのクエリと同じように見えますが、これは 'GROUP BY#ReportDate.dates'を説明します – JamieD77

+0

ループを削除し、代わりに集計テーブルを使用してこれをスピードアップすることもできます。これはおそらく最悪のパーツパフォーマンスではありませんが、ループの代わりにこのセットを作るのは簡単です。ここでは、集計表とそのループをどのように置き換えることができるかを説明する素晴らしい記事があります。 http://www.sqlservercentral.com/articles/T-SQL/62867/ –

+0

@ JamieD77あなたはグループを余計に使っていると言っていますか? –

答えて

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句で相関サブクエリのようなものです。

+0

このクエリを書き換えるには、OUTER APPLYを使用するのが唯一の最良の方法ですか?私は外側の適用が代わりにテーブル値関数のためだと思った –

+0

@ StephenH.Anderson。 。 。論理を書くのが最も明白な方法です。サブクエリは1つの値しか返すことができないため、その問題を回避します。私は論理を理解していないので、もっと簡単に書く方法があるかもしれません。しかし、「APPLY」は、「横方向結合」と呼ばれるものを実装します。テーブル値関数は1つのアプリケーションにすぎません。 –