2016-11-07 73 views
2

我有SQL Server代碼,需要很長時間來運行結果。過去花了15分鐘。但最近,可能由於積累的銷售數據,花了2個小時纔得到結果!SQL Server:通過多種連接關係優化效率

因此,我想獲得關於如何優化代碼的一些建議:

的代碼結構非常簡單:只是爲了獲得銷售款針對不同的時間段和每個SKU不同的區域。 (我已經刪除了一些代碼,這裏是找到不同尺寸的每種材料的不同SKU)。

非常感謝您的幫助。

enter image description here

的主要代碼結構是如下的,因爲它幾乎是一樣的,所以我只給第一2個段落作爲例子:上

SELECT SKU from [MATINFO] 
 

 
-- Global Sales History Qty - All the years 
 

 
\t \t \t LEFT JOIN 
 
\t \t \t (
 
\t \t \t \t SELECT SKU,SUM([SALES Qty]) as [Global Sales History Qty - All the years] 
 
\t \t \t \t from dbo.[SALES] 
 
\t \t \t \t 
 
\t \t \t \t where [PO] IS NOT NULL 
 

 
\t \t \t \t group by SKU 
 

 
\t \t \t)histORy 
 

 
\t \t \t on MATINFO.[SKU]=histORy.[SKU] 
 

 

 
-- Global Sales History Qty - Past 2 years 
 

 
\t LEFT JOIN 
 
\t \t \t (
 
\t \t \t \t SELECT (
 
\t \t \t \t \t SELECT SKU,SUM([SALES Qty]) as [Global Sales History Qty - All the years] 
 
\t \t \t \t \t \t from dbo.[SALES] 
 
\t \t \t \t 
 
\t \t \t \t \t \t where [PO] IS NOT NULL 
 

 
\t \t \t \t \t \t group by SKU 
 

 
\t \t \t \t /* date range */ 
 
\t \t \t \t and ([ORDER DATE] = '2015.11' OR [ORDER DATE] = '2015.12' or [ORDER DATE] like '%2015%' OR [ORDER DATE] like '%2016%') 
 
\t \t \t \t group by SKU 
 
\t \t \t)histORy2 
 

 
\t \t \t on MATINFO.[SKU]=histORy2.[SKU] 
 

 
--Global Sales History Qty - Past 1 years 
 

 
......SIMILAR TO THE CODE STRUCTURE AS ABOVE

+0

在臨時表中實現派生表(帶有合適的索引),並改爲在您的宏查詢中使用臨時表。 –

+0

@ TT,感謝您的及時回覆。這非常有幫助。您能否在「答案區域」輸入您的答覆並舉個簡短的例子,以便我可以採用? –

+0

我的回答加快了您的查詢速度嗎? –

回答

1

擴展我的評論。請注意,這只是一個建議,不能保證運行速度會更快。

看看下面的派生表histORy

SELECT SKU,SUM([SALES Qty]) AS [Global Sales History Qty - All the years] 
FROM dbo.[SALES] 
WHERE [PO] IS NOT NULL 
GROUP BY SKU 

在你運行你的查詢,兌現派生表在臨時表:

SELECT SKU,SUM([SALES Qty]) AS [Global Sales History Qty - All the years] 
INTO #histORy 
FROM dbo.[SALES] 
WHERE [PO] IS NOT NULL 
GROUP BY SKU 

然後使用臨時表查詢:

LEFT JOIN #histORy AS h ON MATINFO.[SKU]=h.[SKU] 

在這種情況下,你可能想要一個inde x在SKU字段中,因此您可以自己創建臨時表,並對其設置索引,並使用INSERT INTO #history... SELECT ...填充。

+0

非常感謝,它的工作原理。我將你和Used_By_Already的方法結合起來,最後只需3分鐘即可獲得結果。 –

+0

不客氣,很高興幫助:)。 –

2

性能較差的最可能原因是對日期使用字符串,並且可能缺少足夠的數據索引。

LIKE「%2015年%」

使用與全表掃描類似的結果雙頭通配符這樣子查詢每次檢索算法不同日期的時間範圍內掃描整個表。使用臨時表不會解決潛在的問題。


[後來添加]

原始查詢結構的另一個方面可能會減少你需要的數據的掃描次數 - 通過使用「有條件的集合體」

例如這裏是你的原始查詢的精簡版本

SELECT 
      SKU 
    FROM [MATINFO] 
    -- Global Sales History Qty - All the years 
    LEFT JOIN (SELECT 
        SKU 
        , SUM([SALES Qty]) AS [Global Sales History Qty - All the years] 
      FROM dbo.[SALES] 
      WHERE [PO] IS NOT NULL 
      GROUP BY 
        SKU) histORy ON MATINFO.[SKU] = histORy.[SKU] 
    -- Global Sales History Qty - Past 2 years 
    LEFT JOIN (SELECT 
        SKU 
        , SUM([SALES Qty]) AS [Global Sales History Qty - Past 2 years] 
      FROM dbo.[SALES] 
      WHERE [PO] IS NOT NULL 
      /* date range */ 
      AND [ORDER DATE] >= '20151101' AND [ORDER DATE] < '20161101' 
      GROUP BY 
        SKU) histORy2 ON MATINFO.[SKU] = histORy2.[SKU] 

這需要在dbo中完成2次數據傳遞。[銷售],但如果是使用SUM內部的情況下的表達()函數,你需要的數據的僅一個通(在這個例子中)

SELECT 
     SKU 
     , SUM([SALES Qty])   AS [Qty_all_years] 
     , SUM(CASE 
       WHEN [ORDER DATE] >= '20151101' AND [ORDER DATE] < '20161101' 
       THEN [SALES Qty] 
     END)      AS [Qty_past_2_years] 
FROM dbo.[SALES] 
WHERE [PO] IS NOT NULL 
GROUP BY 
     SKU 

我懷疑你可以此邏輯適用於大多數的當與日期列和適當的索引結合在一起時,可以大大提高查詢的效率。

+0

非常感謝您的回覆。對不起,我不太明白「在全表掃描中使用類似結果的雙端通配符」。我猜日期範圍可能是原因,但主日期格式不同,有些日期範圍在導入到SQL SERVER後會變爲NULL。所以我必須將它們轉換成某物。像EXCEL中的2015.6(符合ERP中的其他日期格式),然後導入到SQL SERVER中。 –

+0

** like'%2015%'**兩端都有通配符=雙重結尾wilcard =極其低效 –

+0

昨天通過丟棄之前使用字符串進行日期的方法,速度得到了改善,但仍需要1個小時才能完成得到結果。過去花了2個小時。我會嘗試使用臨時表方法,謝謝 –