2016-11-07 62 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个小时。我会尝试使用临时表方法,谢谢 –