所以这个SQL查询工作正常,但需要花费太多时间,大约3分钟〜。我想知道是否有可能优化它。并且在JOIN中使用子查询编写了另一个查询,它运行得更快,但它提供了错误的输出。
我们想要达到的目标是为去年每周的每个严重程度获取所有警报和更多过滤警报。这些过滤的警报在“CCALARMS”子查询中描述(或在其他查询中的“SOMETHING”JOIN中)。
也许有些人知道,如何优化第一个查询,或者如何修改第二个查询,以产生正确的输出?使用MSSQL服务器。提前谢谢!
正确查询(需要很长时间):
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
修改后的查询(占用较少,但输出不正确):
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
还附上输出应该是的图片:
答案 0 :(得分:0)
一个问题是非可搜索的WHERE
子句表达式,它可以有效地阻止FIRSTOCCURRENCEDAY
上的索引(假设存在一个索引):
WHERE DATEDIFF( wk, rSTA.FIRSTOCCURRENCEDAY, GETDATE()) < 54 AND rSEV.NAME != 'Clear'
尝试重构,使该函数不直接应用于列:
WHERE
rSTA.FIRSTOCCURRENCEDAY < DATEADD(week, -54, GETDATE())
AND
rSEV.NAME != 'Clear'
如果仍有问题,请在问题中添加CREATE TABLE
DDL(包括约束和索引),并将实际执行计划上传到https://www.brentozar.com/pastetheplan/。