Рассчитать время простоя - PullRequest
0 голосов
/ 05 октября 2018

Я хотел бы рассчитать время простоя для некоторых процессов.

Мои данные могут выглядеть следующим образом:

Proces    ID     StartTime             EndTime  
A         1      24-07-2018 00:00:00   24-07-2018 00:02:54
A         2      24-07-2018 00:00:16   24-07-2018 00:02:55
A         3      24-07-2018 11:12:42   24-07-2018 11:15:10
A         4      24-07-2018 00:00:16   24-07-2018 00:02:55

В этом примере идентификаторы 1, 2 и 4 перекрываются, но время простоя должно быть только с 00.00.00 до 00.02.55 плюсвремя простоя для идентификатора 3.

Я не уверен, как сравнивать все время, и только заставить его использовать время перекрытия один раз.

Если неясно, тогда спросите!

Я надеюсь, что кто-то может мне помочь.

Ответы [ 3 ]

0 голосов
/ 05 октября 2018

Может быть решено с помощью самостоятельного объединения следующим образом

select t.process, sum(datediff(second, t.StartTime, t.EndTime))
from
(
  select distinct d1.process, min(d2.StartTime) StartTime, max(d2.EndTime) EndTime
  from data d1
  left join data d2 on d2.EndTime > d1.StartTime and d2.StartTime < d1.EndTime
  group by d1.process, d1.id
) t
group by t.process

DBFiddle DEMO

Однако производительность для больших данных может быть довольно низкой.По крайней мере, индексы на (process, id, endtime) и (process, id, starttime) должны быть доступны.

0 голосов
/ 09 октября 2018

Не могли бы вы попробовать выполнить SQL-запрос с большим количеством данных

Пожалуйста, попробуйте также создать пример данных для различных процессов

Этот запрос суммирует время простоя, сгруппированное по процессам, вы можете удалить процесс из агрегацииОператор SELECT (последний запрос) для расчета общего времени простоя.Или даже добавьте GroupId в список для простоев в цепочках перекрывающихся периодов простоя

Пожалуйста, посмотрите учебник SQL по SQL-запросам для перекрывающихся периодов времени , который подробно объясняет решение

;with rawdata as (
    select
        Process, id, StartTime, EndTime,
        ROW_NUMBER() over (partition by Process order by StartTime, EndTime) as rn
    from Processes
), cte as (
    select
        Process, StartTime, EndTime, rn, 1 as GroupId
    from rawdata
    where rn = 1

    union all

    select
        p1.Process,
        case 
        when (p1.starttime between p2.starttime and p2.endtime) then p2.starttime
        when (p2.starttime between p1.starttime and p1.endtime) then p1.starttime
        when (p1.starttime < p2.starttime and p1.endtime > p2.endtime) then p1.starttime
        when (p1.starttime > p2.starttime and p1.endtime < p2.endtime) then p2.starttime
        else p2.starttime
        end as StartTime, 

        case 
        when (p1.EndTime between p2.starttime and p2.endtime) then p2.EndTime
        when (p2.endtime between p1.starttime and p1.endtime) then p1.endtime
        when (p1.starttime < p2.starttime and p1.endtime > p2.endtime) then p1.endtime
        when (p1.starttime > p2.starttime and p1.endtime < p2.endtime) then p2.endtime
        else p2.endtime
        end as EndTime, 

        p2.rn,
        case when
            (p1.starttime between p2.starttime and p2.endtime) or
            (p1.endtime between p2.starttime and p2.endtime) or
            (p1.starttime < p2.starttime and p1.endtime > p2.endtime) or
            (p1.starttime > p2.starttime and p1.endtime < p2.endtime) 
        then
            p1.GroupId
        else 
            (p1.GroupId+1)
        end as GroupId
    from cte p1
    inner join rawdata p2
        on p1.Process = p2.Process and
           (p1.rn+1) = p2.rn
)
select 
    Process,
    sum(datediff(second, StartTime, EndTime)) totalDownTime
from (
    select
        Process, GroupId, min(StartTime) StartTime, max(EndTime) EndTime
    from cte
    group by Process, GroupId
) t
group by Process

Вывод выглядит следующим образом

enter image description here

Надеемся быть полезным,

0 голосов
/ 05 октября 2018

Я думаю, что лучше справляться с этой задачей вне TSQL. Например, в вашем Приложении вы можете получать каждый день и использовать битовый массив для каждой минуты и рассчитывать минимальное и максимальное время в каждом перекрывающемся диапазоне.это очень сложно в TSQL, и я думаю, что у каждого решения есть ПРОБЛЕМА Производительности.

...