几天来,我一直在努力解决这个问题.我有一台可能有错误的机器.在数据库中,我有错误出现时的开始和结束时间(在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
我需要找到这台机器的总错误持续时间.我无法总结上表中的所有差异,因为在同一时间间隔内可能出现两个或更多错误.记录按升序排序.
我的猜测是将每个记录(开始和结束时间)与之前进行比较,然后找出以秒为单位的差异.但是,此表可能会随着时间的推移而增长,搜索它是一个问题.
2间隔案例
当添加两个区间[a,b]和[c,d],因此(d-c)(b-a)时,将它们的重叠计算两次.
>如果重叠不为零,则其值为min(b,d) – max(a,c).由于您在间隔开始时对项目进行了排序,因此您知道max(a,c)== c.
>如果重叠为0,则< = b< = c< = d所以min(b,d)== b,max(a,c)== c和min(b,d) - max (a,c)== b - c< = 0.然而,你想要删除0.
因此通式为d-c b-a-max(0,min(b,d)-c)
推广到更多的间隔
要概括为多于两个的间隔,只需考虑当您将新间隔[c,d]添加到任意数量的先前间隔时,添加(dc)并且计算两次的重叠在[c,d]和之间所有先前间隔的联合.
由于您对其起始值进行了间隔排序,因此您只需要考虑此并集的最后一个连续间隔,从而为您提供最后一个连续的停机时间段.
如果[a,b]是您之前的最后一个连续间隔,并且您刚刚添加了[c,d]:
>如果[a,d]重叠,则最后一个连续间隔变为[a,max(b,d)],因为这是[a,d]的并集
>如果[a,d]不重叠,则最后一个连续间隔变为[c,d](注意:我们有max(b,d)== b)
因为< c由于排序的间隔,间隔重叠iff c < b 在代码中 这可能比在MysqL中更容易在PHP中实现.在伪代码中,假设每行返回(开始,结束)错误间隔,[a,b]是您最后一次知道的连续间隔:
(a,b) = get_first_row();
downtime = b-a;
while( (c,d) = get_next_row() )
{
downtime += d-c - max(0,min(d,b)-c);
a = c < b ? a : c;
b = max(b,d);
}
您可以在此处看到此代码成功运行:https://3v4l.org/Q2phs