2017-03-01 50 views
-2

我有下面的查詢,我已經刪除了它的大部分,因爲有大約20個條件,它將只是太長和複雜的投入。我的查詢工作,我得到的數據是完全一樣,我想它是我的當年的數字和我以前的(數字)。這是通過前一年的一些子查詢來實現的,我從當前財政年度減去1。現在,當我的查詢變得更加複雜時,由於我擁有大量數據,我添加了其他15個子查詢,它有時可能需要超過12小時才能運行。有沒有更有效的方式來編寫這個查詢?如何讓我的查詢更高效?

編輯

不知道爲什麼,在一個完全有效的問題,這麼多downvotes。

SELECT 
     period, 
     finyear, 
     fin_week, 
     region, 
     store, 
     salesperson, 

     SUM(Fin_Revenue) as total_rev_ty, 
     SUM(CASE WHEN status_rev IN ('refund') THEN Fin_Revenue ELSE 0 END) as refund_rev_ty, 
     SUM(CASE WHEN status_rev IN ('credit') Fin_Revenue ELSE 0 END) as credit_rev_ty, 

      (
      SELECT SUM(Fin_Revenue) 
      FROM [MYDB] r2 
      where r1.store = r2.store 
      AND r1.fin_week = r2.fin_week 
      AND r1.Salesperson = r2.Salesperson 
      AND r1.fin_yr = dateadd(yy,1,r2.fin_yr) 
     ) as total_rev_ly, 


      (
      SELECT SUM(CASE WHEN status_rev IN ('refund') THEN Fin_Revenue ELSE 0 END) 
      FROM [MYDB] r2 
      where r1.store = r2.store 
      AND r1.fin_week = r2.fin_week 
      AND r1.Salesperson = r2.Salesperson 
      AND r1.fin_yr = dateadd(yy,1,r2.fin_yr) 
     ) as refund_rev_ly, 

     (SELECT 
     SUM(CASE WHEN status_rev IN ('credit') Fin_Revenue ELSE 0 END) 
      FROM [MYDB] r2 
      where r1.store = r2.store 
      AND r1.fin_week = r2.fin_week 
      AND r1.Salesperson = r2.Salesperson 
      AND r1.fin_yr = dateadd(yy,1,r2.fin_yr) 
     ) as refund_rev_ly 

FROM [MYDB] r1 

     WHERE 
     fin_yr IN ('2016') 
+2

包含'FROM'子句的實際上可能會鼓勵它運行。 –

+3

@GordonLinoff,但它現在的方式是非常有效的!它非常及時地返回錯誤消息,並且不掃描任何表。 –

+0

我很喜歡這種事情。 FROM語句現在在那裏。建設性的幫助可能比諷刺評論更好。謝謝。 – 80gm2

回答

2

case語句使您的查詢以順序模式運行,並使其非常緩慢。 你可以改變你的子查詢到這一點:

(
    SELECT SUM(Fin_Revenue) as refund 
    FROM [MYDB] r2 
    where r1.store = r2.store 
    AND r1.fin_week = r2.fin_week 
    AND r1.Salesperson = r2.Salesperson 
    AND r1.fin_yr = dateadd(yy,1,r2.fin_yr) 
    AND status_rev ='refund' 
) as refund_rev_ly, 

(SELECT SUM(Fin_Revenue) as credit 
    FROM [MYDB] r2 
    where r1.store = r2.store 
    AND r1.fin_week = r2.fin_week 
    AND r1.Salesperson = r2.Salesperson 
    AND r1.fin_yr = dateadd(yy,1,r2.fin_yr) 
    AND status_rev = 'credit' 
) as refund_rev_ly 

如果你有一個索引status_rev列,子查詢將運行得更快。

還有其他可以改進的地方,但這是我建議的侵入性最小的方法。

+0

你能否建議入侵者?我非常樂意嘗試這些,甚至只是意識到它們。你還可以更多地解釋順序模式。非常感謝。 – 80gm2

+1

我的意思是'順序'搜索是數據庫引擎檢查表中的每一條記錄。因此,如果您有10,000行,則退款子查詢將讀取並檢查10,000行以獲取結果,而信用子查詢也會執行相同的操作。如果您在status_rev列上定義索引,那麼這些子查詢中的每一個都只會讀取在該列中具有特定值的行,這意味着所提取的行數較少。 SQL服務器對索引使用非常先進的算法 – Sparrow

+1

如果使用查詢的「執行計劃」,可以看到SQL服務器正在執行什麼操作來獲取查詢結果。這是一個非常廣泛的話題,所以我無法在這裏解釋它,但我建議您閱讀它以瞭解如何在查詢中處理性能增強。 – Sparrow