So there's this SQL query which works fine, but takes too much time, around 3 minutes~. I wonder would it be possible to optimize it. And there's another query written with a subquery in a JOIN, which works faster, but it provides wrong output.
What we want to achieve is to get all alarms and more filtered alarms for every severity of every week of last year passed. Those filtered alarms are described in "CCALARMS" subquery (or in "SOMETHING" JOIN in other query ).
Maybe some of you know, how to optimize the first query, or how to modify second query, to produce correct output? Using MSSQL server. Thanks in advance!
Correct Query (takes long time):
SELECT
DATEPART( yy, rSTA.FIRSTOCCURRENCEDAY ) AS YEAR,
DATEPART( wk, rSTA.FIRSTOCCURRENCEDAY ) AS MONTH,
rSEV.NAME AS SEVERITY,
COUNT(rSTA.ALARMIDKEY) AS ALARMS,
CCALARMS = COUNT(
CASE WHEN
(MAINTMODECRONTAB != 'Y'
AND SUPPRESSESCL < 4
AND SPMAUTO != 1
AND ORIGINALSEVERITY > 0)
AND ((AIWAVER = 3 AND EVENTACTOR = 1)
OR
((AIWAVER < 3 OR AIWAVER IS NULL)
AND ((CONTROLCENTREVIEW = 1
AND ORIGINALSEVERITY = 5)
OR (CONTROLCENTREVIEW = 2)
OR (ALERTGROUP = 'CHECKLIST')
)
)
)
THEN rSTA.ALARMIDKEY END)
FROM
REPORTER.reporter.REPORTER_STATUS rSTA
INNER JOIN
REPORTER.reporter.REP_SEVERITY_TYPES rSEV
ON
rSTA.ORIGINALSEVERITY = rSEV.SEVERITY
WHERE
DATEDIFF( wk, rSTA.FIRSTOCCURRENCEDAY, GETDATE()) < 54
AND
rSEV.NAME != 'Clear'
GROUP BY
DATEPART( yy, rSTA.FIRSTOCCURRENCEDAY ),
DATEPART( wk, rSTA.FIRSTOCCURRENCEDAY ),
rSEV.NAME
ORDER BY
DATEPART( yy, rSTA.FIRSTOCCURRENCEDAY ) DESC,
DATEPART( wk, rSTA.FIRSTOCCURRENCEDAY ) DESC
Modified query (takes less, but output is not correct):
SELECT
DATEPART( yy, rSTA.FIRSTOCCURRENCEDAY ) AS YEAR,
DATEPART( wk, rSTA.FIRSTOCCURRENCEDAY ) AS MONTH,
rSEV.NAME AS SEVERITY,
COUNT(rSTA.ALARMIDKEY) AS ALARMS,
SOMETHING.ALARMIDKEY_CC_ACTS
FROM
REPORTER.reporter.REPORTER_STATUS rSTA
INNER JOIN
REPORTER.reporter.REP_SEVERITY_TYPES rSEV
ON
rSTA.ORIGINALSEVERITY = rSEV.SEVERITY
JOIN
(
SELECT ALARMIDKEY, COUNT(ALARMIDKEY) AS ALARMIDKEY_CC_ACTS FROM REPORTER.reporter.REPORTER_STATUS WHERE
(MAINTMODECRONTAB != 'Y'
AND SUPPRESSESCL < 4
AND SPMAUTO != 1
AND ORIGINALSEVERITY > 0)
AND ((AIWAVER = 3 AND EVENTACTOR = 1)
OR
((AIWAVER < 3 OR AIWAVER IS NULL)
AND ((CONTROLCENTREVIEW = 1
AND ORIGINALSEVERITY = 5)
OR (CONTROLCENTREVIEW = 2)
OR (ALERTGROUP = 'CHECKLIST')
)
)
)
GROUP BY ALARMIDKEY ) AS SOMETHING
ON SOMETHING.ALARMIDKEY = rSTA.ALARMIDKEY
WHERE
DATEDIFF( wk, rSTA.FIRSTOCCURRENCEDAY, GETDATE()) < 54
AND
rSEV.NAME != 'Clear'
GROUP BY
DATEPART( yy, rSTA.FIRSTOCCURRENCEDAY ),
DATEPART( wk, rSTA.FIRSTOCCURRENCEDAY ),
rSEV.NAME,
SOMETHING.ALARMIDKEY_CC_ACTS
ORDER BY
DATEPART( yy, rSTA.FIRSTOCCURRENCEDAY ) DESC,
DATEPART( wk, rSTA.FIRSTOCCURRENCEDAY ) DESC
Also attaching pictures of what the output should be:
One issue is the non-sargable WHERE
clause expression that prevents an index on FIRSTOCCURRENCEDAY
efficiently (assuming one exists):
WHERE DATEDIFF( wk, rSTA.FIRSTOCCURRENCEDAY, GETDATE()) < 54 AND rSEV.NAME != 'Clear'
Try refactoring such that the function is not applied to the column directly:
WHERE
rSTA.FIRSTOCCURRENCEDAY < DATEADD(week, -54, GETDATE())
AND
rSEV.NAME != 'Clear'
If you still have problems, add CREATE TABLE
DDL to your question (including constraints and indexes) and upload your actual execution plans to https://www.brentozar.com/pastetheplan/ .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.