2011-05-06 66 views
1

我做在PHP中的程序,在MySQL数据库中存储时它的工作。显示该程序是否工作或没有该表看起来是这样的:PHP计算“停机”

Table_name: downtime 
Working(int) Time(datetime) 
1    2011-05-06 15:18:55 
0    2011-05-06 15:20:21 
1    2011-05-06 15:20:24 
0    2011-05-06 16:05:13 
1    2011-05-06 16:05:15 
0    2011-05-06 16:27:59 
1    2011-05-06 16:28:01 
0    2011-05-06 16:37:35 
1    2011-05-06 16:37:37 

现在我想以检索日期之间的“停机”。说日期1是2011-05-06 15:20:24和日期2是2011-05-06 16:28:15,那么我希望脚本返回该时期1和0之间差异的总和。我怎样才能做到这一点?

重要的是知道何时日期1例如为2011-05-06 15点20分22秒,然后有两个额外的秒的停机时间。很难想象一个(几乎)完美的解决方案。

回答

1

我现在使用的解决方案是:

$objects = Get("table","`date` BETWEEN '".$date_start."' AND '".$date_end."'"); 

    $prev = new stdClass(); 
    $prev->new = 1; 
    $prev->date = $date_start; 

    $next = new stdClass(); 
    $next->new = 0; 
    $next->date = $date_end; 
    $objects = array_merge(array($prev),$objects,array($next)); 

    $uptime = 0; 
    $downtime = 0; 
    $prevtime = false; 
    foreach($objects as $object) 
    { 
     $newtime = strtotime($object->date); 
     if($prevtime && $object->new == 1) 
     { 
      $downtime += $newtime - $prevtime; 
     } 
     elseif($prevtime && $object->new == 0) 
     { 
      $uptime += $newtime - $prevtime; 
     } 
     $prevtime = $newtime; 
    }  

的get();是我的功能传达给数据库:它返回一个对象(记录)通过查询发现,随着如果你想测试/使用此代码替换为以下:

$objects = array(); 
$result = mysql_query("SELECT * FROM table WHERE `date` BETWEEN '".$date_start."' AND '".$date_end."'"); 
while($object = mysql_fetch_object($result)) 
{ 
    $objects[] = $object;  
} 
-1

编辑:我误解了这个问题,忽略了这个答案

答案在很大程度上取决于你如何存储在MySQL数据。你很可能需要一个像这样的查询:

SELECT COUNT(*) FROM table WHERE working='1' AND DATE>='startDate' AND DATE<='endDate'; 

这将给你在给定范围内'1的数量。

+0

MySQL表是在quetion,所以这就是它存储的方式;) – Simon 2011-05-06 16:50:11

+0

你为我的投票支持_answering你的问题! 你的问题并没有规定是从你的MySQL的提取物,或列的数据类型。无论如何,我的答案应该有效。 – 2011-05-06 16:54:12

+0

那不是我!)反正你不回答我的问题... – Simon 2011-05-06 16:55:31

1

通过所有的行与strtotime()转换时间戳UNIX时代,那么只要找到它们之间的差别,并添加后拿到总停机时间。

+0

这在PHP中看起来像什么?很难找到正确的代码作为问题的答案 – Simon 2011-05-06 17:25:22

0
select timediff(
(
    select `time` 
    from downtime 
    where working = 1 
    and `time` > t1.`time` 
    order by `time` asc 
    limit 1 
), 
t1.`time` 
) 
from downtime t1 
where t1.working = 0 

这应该给你几行,每个停机时间段一个。每一行显示时间差异,您仍然必须将这些行添加到一起才能找到实际的停机时间。我不确定当你在时间差异上使用MySQL的sum()函数时会发生什么,它可能只是返回秒。您可以根据需要限制time字段,但我尚未测试在开始时间或结束时间处于停机时间段时会发生的情况。

2

此代码应该工作,我和你的榜样的数据进行了测试:

// Example data 
// Note: assumes $data is sorted by date already 
$data = array(
    "2011-05-06 15:18:55"=>1, 
    "2011-05-06 15:20:21"=>0, 
    "2011-05-06 15:20:24"=>0, 
    "2011-05-06 16:05:13"=>0, 
    "2011-05-06 16:05:15"=>0, 
    "2011-05-06 16:27:59"=>1, 
    "2011-05-06 16:28:01"=>0, 
    "2011-05-06 16:37:35"=>0, 
    "2011-05-06 16:37:37"=>1 
    ); 

$startTime = strtotime("2011-05-06 15:18:55"); 
$endTime = strtotime("2011-05-06 16:28:01"); 

$totalUptime = 0;  
$lastUptime = 0; 

foreach ($data as $dateString => $isWorking) 
{ 
    $timestamp = strtotime($dateString); 

    if ($lastWorking && $lastTimestamp) 
    { 
     $allowedStart = $lastTimestamp; 
     if ($allowedStart<$startTime) 
      $allowedStart = $startTime; 

     $allowedEnd = $timestamp; 
     if ($allowedEnd>$endTime) 
      $allowedEnd = $endTime; 

     $diff = $allowedEnd-$allowedStart; 

     if ($diff>0) 
     { 
      $totalUptime += $diff; 
     } 
    } 

    if ($timestamp>=$endTime) 
    { 
     break; 
    } 

    $lastTimestamp = $timestamp;  
    $lastWorking = $isWorking; 
} 

print "Total uptime: ".$totalUptime." seconds"; 

你只需要填充$data从数据库中自己的记录。

+0

如果我有大约10000条记录怎么办?我应该如何选择它们 – Simon 2011-05-06 17:56:55

+1

只要您在测试的日期范围内有记录,此代码就会工作,并且会在更早和更晚的时间记录一条记录。所以我建议查询日期范围加上一点点(一天一小时? - 取决于你更新的频率)。额外的几条记录不会显着减慢脚本速度。 – 2011-05-06 18:11:40