0

我想计算一些进程的停机时间。

我的数据可能如下所示:

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 的停机时间。

我不知道如何比较所有时间并且只让它使用重叠时间一次。

如果不清楚,那就问吧!

我希望有一个人可以帮助我。

4

3 回答 3

0

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

于 2018-10-05T10:47:34.957 回答
0

您能否尝试使用更多数据执行 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

输出如下

在此处输入图像描述

希望有用,

于 2018-10-09T05:57:41.080 回答
0

可以使用自加入解决如下

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 演示

但是,大数据的性能可能很差。至少索引(process, id, endtime)并且(process, id, starttime)应该可用。

于 2018-10-05T11:07:23.757 回答