Without knowing your output, here's some things that jump out to me as typically costly syntax:
- Replace CURSORS with Set-based logic (as the previous post suggested), or, try a LOOP instead
- Do you need the "Select distinct" in your cursor? ... Distinct is a more expensive command
- For Where ISNULL(LimitCoefficient, 0) > 0 ... Could this instead read "where LimitCoefficient > 0" (preventing RBAR)
- Can parts of your where criteria be done on the tables prior to the joins by including them as Virtual tables? (see example below)
- Is a Order by necessary? .... For millions of rows this is VERY costly
Try running your execution plan to see if you can identify a particular task that is taking the bulk of the processing time
Here's a VT example:
declare @StartDate datetime
set @StartDate = DATEADD(month, -1, @CurrentDateTime)
declare @EndDate datetime
set @EndDate = DATEADD(day, 1, @CurrentDateTime)
SELECT DISTINCT
E.EquipmentNumber_FK,
E.Floor,
P.SNRule_PK,
P.AttributeStat,
P.CEN_FK,
P.LimitCoefficient,
P.MessageType_FK,
P.EquipmentClass_FK,
P.RemoteMonitoringType_FK,
P.AnalyzerType_FK
FROM SNRuleFaultsPerStat P
INNER JOIN
(Select EquipmentNumber_FK,
[Floor],
Cen,
RemoteMonitoringType_FK
from Event
where StartTimestamp BETWEEN @StartDate AND @EndDate
) E
ON P.CEN_FK = E.CEN
AND P.RemoteMonitoringType_FK = E.RemoteMonitoringType_FK
INNER JOIN Equipment EQ
ON P.EquipmentClass_FK = EQ.EquipmentClass_FK
AND P.RemoteMonitoringType_FK = EQ.RemoteMonitoringType_FK
AND P.AnalyzerType_FK = EQ.AnalyzerType_FK
AND E.EquipmentNumber_FK = EQ.EquipmentNumber
WHERE
ISNULL(LimitCoefficient, 0) > 0 AND
AttributeStat = 'STARTS' AND
--E.StartTimestamp BETWEEN DATEADD(month, -1, @CurrentDateTime) AND DATEADD(day, 1, @CurrentDateTime) AND
P.FloorByFloor = '1'