• 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'