计算停机时间

时间:2018-10-05 08:54:58

标签: sql-server downtime

我想计算某些流程的停机时间。

我的数据可能像这样:

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

在此示例中,ID 1、2和4是重叠的,但是停机时间只能在00.00.00到00.02.55之间加上ID 3的停机时间。

我不确定如何比较所有时间,只知道一次使用重叠时间。

如果不清楚,请询问!

我希望有人能帮助我。

3 个答案:

答案 0 :(得分:0)

我认为最好用TSQL处理此业务,例如,在您的应用程序中,您可以每天获取并使用每分钟的位数组,并计算每个重叠范围内的最小和最大时间。 这在tsql中非常复杂,我认为每个解决方案都有性能问题。

答案 1 :(得分:0)

可以通过如下所示的自连接来解决

(process, id, endtime)

DBFiddle DEMO

但是,大数据的性能可能会很差。至少应该有(process, id, starttime)和{{1}}上的索引。

答案 2 :(得分:0)

能否请您尝试对SQL查询添加更多数据

请也尝试为不同的流程创建示例数据

此查询汇总按进程分组的停机时间,您可以从聚合SELECT语句(这是最后一个查询)中删除进程以计算总体停机时间。甚至将GroupId添加到列表中,以获取每段重叠的停机时间段的停机时间

请参阅SQL Queries for Overlapping Time Periods上的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

希望有用,