2017-06-07 93 views
0

我在SQL Server上有一个需要优化的SQL查询。 运行它需要将近16分钟。在SQL Server上优化SQL查询

SELECT DISTINCT DeptNo, 
       BrandDesc, 
       MfgDesc, 
       CountOfActiveSKUs = 
        COALESCE((SELECT COUNT(*) 
           FROM dbo.SKU k 
           WHERE k.Status = 'A' 
           AND k.BrandDesc = s.BrandDesc 
           AND k.MfgDesc = s.MfgDesc 
           AND k.DeptNo = s.DeptNo), 
          0) 
      FROM dbo.SKU s 
     ORDER BY BrandDesc 

我想出了以下内容,但它似乎并不抓住它有CountOfActiveSKUs = 0

SELECT DISTINCT DeptNo, 
       BrandDesc, 
       MfgDesc, 
       CountOfActiveSKUs = COALESCE(Count(*), 0) 
      FROM dbo.SKU 
      WHERE Status = 'A' 
     GROUP BY BrandDesc, MfgDesc, DeptNo 
     ORDER BY BrandDesc 

任何帮助表示赞赏记录, 谢谢!

+0

对于记录来说,在select中使用相关子查询几乎总是一个糟糕的选择。请完全停止使用这种技术。因为它是一个性能杀手,而且几乎没有必要。 – HLGEM

+0

@HLGEM同意,谢谢! – Springray

回答

3

我会写为:

SELECT DeptNo, BrandDesc, MfgDesc, 
     SUM(CASE WHEN status = 'A' THEN 1 ELSE 0 END) OVER (PARTITION BY BrandDesc, MfgDesc, DeptNo) as CountOfActiveSKUs 
FROM dbo.SKU s 
ORDER BY BrandDesc; 

我将离开SELECT DISTINCT出来,除非它是绝对必要的。如果有必要,则使用一个明确的GROUP BY

SELECT DeptNo, BrandDesc, MfgDesc, 
     SUM(CASE WHEN status = 'A' THEN 1 ELSE 0 END) as CountOfActiveSKUs 
FROM dbo.SKU s 
GROUP BY DeptNo, BrandDesc, MfgDesc 
ORDER BY BrandDesc; 
+0

谢谢戈登!你写的第一个查询在结果上有重复记录,但第二个查询很好用! – Springray

+0

@Springray。 。 。明确的“GROUP BY”是正确的方法。 –

+0

我同意,谢谢! – Springray

1

不要过滤状态,用状态=“A”使用条件的总和计数的SKU。

SELECT DISTINCT DeptNo, 
       BrandDesc, 
       MfgDesc, 
       SUM(CASE WHEN status = 'A' THEN 1 ELSE 0 END) as CountOfActiveSKUs 
      FROM dbo.SKU 
     GROUP BY BrandDesc, MfgDesc, DeptNo 
     ORDER BY BrandDesc 
+0

谢谢伊戈尔!它很棒! – Springray

0

尝试此

SELECT s.DeptNo, s.BrandDesc, s.MfgDesc, count(k.Status) as CountOfActiveSKUs 
FROM dbo.SKU s LEFT OUTER JOIN 
dbo.SKU k ON 
k.Status = 'A' AND k.BrandDesc = s.BrandDesc 
AND k.MfgDesc = s.MfgDesc AND k.DeptNo = s.DeptNo 
GROUP BY s.DeptNo, s.BrandDesc, s.MfgDesc 
ORDER BY BrandDesc 
1

[1]首先,我会重新写从而原始查询:

SELECT DeptNo, BrandDesc,MfgDesc, SUM(IIF(s.Status = 'A', 0, 1)) AS Count_StatusA 
FROM dbo.SKU AS s 
GROUP BY s.DeptNo, s.BrandDesc, s.MfgDesc 
-- ORDER BY s.BrandDesc -- Uncomment this line only when necessary 

[2]然后,我会创建以下索引

CREATE /*UNIQUE*/ /*[NON]CLUSTERED*/ INDEX IUN_SKU_BrandDesc_DeptNo_MfgDesc 
ON dbo.SKU (BrandDesc, DeptNo, MfgDesc, Status) 

说明#1:IIF(表达式,T,F)(SQL2012 +)可以与CASE代替WHEN EXPR则T ELSE六最终

注2:检查是否有重复/相似指数(上dbo.SKU表)

注意#3:索引还应该包括de Status列。

+0

看看第一个音符。 –

+0

对不起Bogdan,我打算给其他SQL初学者(比如我自己)上的信息,因为在第一个注释中声明,因为它不在SQL Server 2008 R2中受支持,所以需要替换它。我也很感谢你的索引信息。谢谢! – Springray