没有重叠mysql的timediff的总和

时间:2018-07-23 07:29:42

标签: mysql

我有一个像这样的MySql表:

$sql = '
  SELECT c.*
  FROM `child` AS c
  WHERE  '
  c.`id` > 0
  ' ORDER BY c.`rank` DESC ';

我必须找到机器运行的时间以及什么都不做的时间。 因此,机器运行的时间很容易。它只是开始时间和结束时间的时差。

但是对于表中运行的每台机器,我都需要一行“机器什么也不做”。在我看来,我必须从一台机器无重叠地运行的总时间中减去属于一台机器的所有活动的时间差,但是我不知道如何做到这一点。

因此对于上表,我需要这样的输出

ID  | activity        | start               | end
372 | Machine Running | 2018-01-30 21:19:42 | 2018-01-30 21:52:41
373 | Order Active    | 2018-01-30 21:19:42 | 2018-01-30 21:45:02
374 | Operator Active | 2018-01-30 21:19:42 | 2018-01-30 21:52:41
375 | Reporting Active| 2018-01-30 21:19:48 | 2018-01-30 21:20:06
376 | Admin Active    | 2018-01-30 21:20:09 | 2018-01-30 21:52:41
378 | Order Active    | 2018-01-30 21:49:23 | 2018-01-30 21:52:41
982 | Machine Running | 2018-02-20 15:01:55 | 2018-02-20 15:01:55
983 | Order Active    | 2018-02-20 15:01:55 | 2018-02-20 15:01:55
984 | Operator Active | 2018-02-20 15:01:55 | 2018-02-20 15:01:55
986 | Machine Running | 2018-02-20 15:02:30 | 2018-02-20 15:02:30
987 | Order Active    | 2018-02-20 15:02:30 | 2018-02-20 15:02:30
988 | Operator Active | 2018-02-20 15:02:30 | 2018-02-20 15:02:30

1 个答案:

答案 0 :(得分:0)

对于类型为Machine Running的每个间隔,您将需要找到类型为Operator Active的所有重叠间隔-我的意思是Machine RunningOperator Active之间的重叠。然后,您必须从相应的Operator Active中减去每个Machine Running重叠。最终结果将是Doing nothing的持续时间。

为此,您将需要一个公式来计算两个时间间隔之间的重叠

GREATEST(0,interval_1_end - interval_1_start - GREATEST(0,interval_1_end - interval_2_end) - GREATEST(0,interval_2_start - interval_1_start))

间隔必须表示为UNIX时间戳。

然后是这样的

SELECT t1.start, UNIX_TIMESTAMP(t1.end) - UNIX_TIMESTAMP(t1.start) AS total_time, SUM(
GREATEST(0,UNIX_TIMESTAMP(t1.end) - UNIX_TIMESTAMP(t1.start)
  - GREATEST(0,UNIX_TIMESTAMP(t1.end) - UNIX_TIMESTAMP(t2.end)) 
  - GREATEST(0,UNIX_TIMESTAMP(t2.start) - UNIX_TIMESTAMP(t1.start)))
) AS do_nothing /* duration in seconds */
FROM tbl AS t1
LEFT JOIN tbl AS t2 ON (t2.start BETWEEN t1.start AND t1.end)
  OR (t2.end BETWEEN t1.start AND t1.end)
WHERE t1.activity = 'Machine Running' AND t2.activity = 'Operator Active'
GROUP BY t1.start