查找重叠值的时间总和

时间:2014-12-01 16:06:14

标签: php mysql math

我一直在努力解决这个问题。我有一台可能有错误的机器。在数据库中,我有错误出现时的开始和结束时间(在unix时间),以及错误类型(数字从5到12)。我遇到的问题是多个错误可能同时发生(并重叠)。

我的表格如下:

   id| type | from       | to
    1| 6    | 1417179933 | 1417180006
    2| 6    | 1417180035 | 1417180065
    3| 9    | 1417180304 | 1417180409
    4| 6    | 1417180662 | 1417184364
    5| 8    | 1417180662 | 1417186832
    6| 9    | 1417180662 | 1417184364
    7| 12   | 1417180662 | 1417184364
    8| 6    | 1417184364 | 1417186832
    9| 9    | 1417184364 | 1417188054

我需要找到这台机器的总错误持续时间。我无法总结上表中的所有差异,因为可能在同一时间间隔内出现两个或更多错误。记录按升序排序。

我的猜测是将每个记录(开始和结束时间)与之前进行比较,然后找出以秒为单位的差异。但是,此表可能会随着时间的推移而增长,搜索它是一个问题。

在PHP或MySQL中是否有一种聪明的方法可以找到机器无法工作的总时间,可能只需几分钟?

3 个答案:

答案 0 :(得分:3)

这是一种总结间隔的一般方法,考虑到潜在的重叠,假设间隔按其较低的值排序。

2个间隔案例

添加两个时间间隔[a,b][c,d]时,(d-c) + (b-a)会将其重叠计算两次。

  • 如果重叠非零,则其值为min(b,d) - max(a,c)。由于您在间隔开始时对项目进行了排序,因此您知道max(a,c) == c

  • 如果重叠为0 ,则a <= b <= c <= dmin(b,d) == bmax(a,c) == cmin(b,d) - max(a,c) == b - c <= 0。然而,你想要删除0

因此,通用公式为d-c + b-a - max(0,min(b,d)-c)

推广到更多间隔

要概括为多于两个的间隔,只需考虑在向任意数量的先前间隔添加新间隔[c,d]时,添加(d-c),并且计算两次的重叠在{{之间1}}以及所有先前间隔的并集。

由于您对其起始值进行了间隔排序,因此您只需要考虑此联合的最后一个连续间隔,从而为您提供最后一个连续的停机时间。

如果[c,d]是您之前的上一个连续间隔,而您刚刚添加了[a,b]

  • 如果[c,d][a,b]重叠,您的上一个连续间隔将变为[c,d],因为这是[a, max(b,d)]和{{1}的联合}
  • 如果[a,b][c,d]不重叠,您的上一个连续间隔将变为[a,b](注意:我们有[c,d]

由于排序的时间间隔为[c, d],因此时间间隔重叠iff max(b,d) == b

代码

这可能比在mysql中更容易在php中实现。在伪代码中,假设每一行返回一个(开始,结束)错误间隔,而a < c是您最后一次知道的连续间隔:

c < b

您可以在此处看到此代码成功运行:https://3v4l.org/Q2phs

答案 1 :(得分:1)

从Peterm Calculate total time excluding overlapped time & breaks in MySQL

窃取想法
 SELECT SUM(seconds) total
   FROM
 (
   SELECT MAX(to_date) - MIN(from_date) seconds
     FROM
   (
     SELECT from_date, to_date,
            @g := IF(@e BETWEEN from_date AND to_date OR to_date <= @e, @g, @g + 1) g,
            @e := to_date
       FROM my_table CROSS JOIN 
     (
       SELECT @g := 0, @e := NULL
     ) i
      ORDER BY from_date, to_date
   ) q
    GROUP BY g
 ) q;

答案 2 :(得分:0)

非数据库方法。可能会对数据库进行修改。

  Start   Finish
  10      13
  12      15
  16      18 

将开始时间和结束时间一起加入一个带有开始标志的已排序列表或数组中。

  Time           IsStart
10              Yes
12              Yes
13              No
15              No
16              Yes
....

让ActiveCounter = 0,浏览列表 如果IsStart增加ActiveCounter,否则减少 当ActiveCounter变为&gt; 0,错误间隔开始,
当ActiveCounter变为= 0时,错误间隔结束。

Time    ActCnt
10      1       //error state begins
12      2       //it continues
13      1       //still continues
15      0       //the end!  T = 15-10 = 5
16      1       //new error state begins