Home > Blockchain >  Calculate time between events SQL Server
Calculate time between events SQL Server

Time:05-20

I am trying to write query which will calculate time difference between rows in but I fail horribly.

Problem is that events are not always one after another and if this is the case it should return NULL value or skip it completely.

Example table

Time ComputerName RenderedDescription EventDisplayNumber
2022-05-19 14:12:58.400 COMP16 The Event log service was started. 6005
2022-05-19 13:52:46.360 COMP16 The Event log service was stopped. 6006
2022-05-19 13:15:47.417 COMP16 The Event log service was started. 6005
2022-05-08 08:26:11.777 COMP16 The Event log service was started. 6005
2022-05-08 07:30:11.030 COMP16 The Event log service was stopped. 6006
2022-05-01 08:22:37.553 COMP16 The Event log service was started. 6005
2022-05-01 07:30:08.057 COMP16 The Event log service was stopped. 6006
2022-04-24 08:20:55.190 COMP16 The Event log service was started. 6005
2022-04-24 07:30:07.143 COMP16 The Event log service was stopped. 6006

And result which I am trying to get

ComputerName Event Stopped Event Started DifferenceMinutes
COMP16 2022-04-24 07:30:07.143 2022-04-24 08:20:55.190 50
COMP16 2022-05-01 07:30:08.057 2022-05-01 08:22:37.553 52
COMP16 2022-05-08 07:30:11.030 2022-05-08 08:26:11.777 56
COMP16 NULL 2022-05-19 13:15:47.417 NULL
COMP16 2022-05-19 13:52:46.360 2022-05-19 14:12:58.400 20

CodePudding user response:

This will work on your sample data:

with Data as (
    select *,
        case when RenderedDescription like '%started%' then 'S'
             when RenderedDescription like '%stopped%' then 'E' end as Code,
        count(case when RenderedDescription like '%started%' then 1 end)
            over (partition by ComputerName order by "Time" desc) as Grp
    from EventLog
)
select
    ComputerName,
    max(case when Code = 'E' then "Time" end) as EventStopped,
    min(case when Code = 'S' then "Time" end) as EventStarted,
    datediff(second, 
        max(case when Code = 'E' then "Time" end),
        min(case when Code = 'S' then "Time" end)
    ) / 60 as DifferenceMinutes

from Data
group by ComputerName, Grp
order by ComputerName, EventStarted;

If you can both have consecutive starts and stops then try this instead:

with Data as (
    select *,
        case when RenderedDescription like '%started%' then 'S'
             when RenderedDescription like '%stopped%'  then 'E' end as Code,
        lag(
            case when RenderedDescription like '%started%' then 'S'
                 when RenderedDescription like '%stopped%'  then 'E' end
        ) over (partition by ComputerName order by "Time") as LastCode
    from EventLog
), Grouped as (
    select *,
        count(case when LastCode = 'E' and Code = 'S' then null else 1 end)
            over (partition by ComputerName order by "Time") as Grp
    from Data
)
select
    ComputerName,
    max(case when Code = 'E' then "Time" end) as EventStopped,
    min(case when Code = 'S' then "Time" end) as EventStarted,
    datediff(second, 
        max(case when Code = 'E' then "Time" end),
        min(case when Code = 'S' then "Time" end)
    ) / 60 as DifferenceMinutes
from Grouped
group by ComputerName, Grp
order by ComputerName, EventStarted;

https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=d7bd556c49cbca84d025bcd1eedc9771

  • Related