Reputation: 99
I have a SQL query on SQL Server that needs to be optimized. It takes almost 16 minutes to run it.
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
I came up with the following, but it doesn't seems it grabs records that have 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
Any help is appreciated, Thank you!
Upvotes: 0
Views: 75
Reputation: 514
Try this
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
Upvotes: 0
Reputation: 1271003
I would write this as:
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;
I would leave the SELECT DISTINCT
out, unless it is absolutely necessary. If it is necessary, then use an explicit 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;
Upvotes: 3
Reputation: 4410
Don't filter the status, count the SKUs with status='A' using a conditional SUM.
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
Upvotes: 1