计算同一个表上行之间的日期时间行的差异

时间:2018-04-04 22:23:31

标签: mysql datetime time datediff timestampdiff

我有一个表,在触发时保存包含任务,状态和时间的记录:

表格tblwork:

+-------------+------------+---------------------+-----+
| task        | status     | stime               | id  |
+-------------+------------+---------------------+-----+
| A           | 1          | 2018-03-07 20:00:00 | 1   |
| A           | 2          | 2018-03-07 20:30:00 | 2   |
| A           | 1          | 2018-03-07 21:00:00 | 3   |
| A           | 3          | 2018-03-07 21:30:00 | 4   |
| B           | 1          | 2018-03-07 22:30:00 | 5   |
| B           | 3          | 2018-03-07 23:30:00 | 6   |
+-------------+------------+---------------------+-----+

状态1表示开始,2 - 暂停,3 - 结束

然后我需要计算每个任务花费的时间,不包括暂停(状态= 2)。我就是这样做的:

SELECT t1.id, t1.task,
SUM(timestampdiff(second,IFNULL( 
(SELECT MAX(t2.stime) FROM tblwork t2  WHERE t2.task='B' AND t2.stime< t1.stime) ,t1.stime),t1.stime)) myTimeDiffSeconds
FROM tblwork t1 
WHERE t1.task='B' and (t1.status = 1 or t1.status = 3);

现在我想获得所有任务的表格

SELECT t1.id, t1.task,
SUM(timestampdiff(second,IFNULL( 
(SELECT MAX(t2.stime) FROM tblwork t2  WHERE t2.stime< t1.stime) ,t1.stime),t1.stime)) myTimeDiffSeconds
FROM tblwork t1 
WHERE (t1.status = 1 or t1.status = 3) GROUP BY t1.taks

我得到了这个结果:

+-------------+------------+---------------------+
| task        | id         | mytimedifference    |
+-------------+------------+---------------------+
| A           | 1          | 3600                |   
| B           | 3          | 2421217             |
+-------------+------------+---------------------+

A的计算是正确的B是错误的,它应该是3600秒,但我不明白为什么。

1 个答案:

答案 0 :(得分:1)

假设每次暂停和结束都有一个开始,那么这样的事情会不会更直接?

SELECT t.task
   , SUM(TO_SECONDS(t.stime) 
         * CASE WHEN t.status IN (1) THEN -1
                WHEN t.status IN (2, 3) THEN 1
                ELSE 0
           END
     ) AS totalTimeSecs
FROM tblwork AS task
GROUP BY t.task

我不太清楚TO_SECONDS()产生的值对于当前时间戳有多大;但如果在总结时它们是一个问题,可以改为

   , SUM((TO_SECONDS(t.stime) - some_constant_just_before_or_at_your_earliest_seconds)
         * CASE WHEN t.status IN (1) THEN -1
                WHEN t.status IN (2, 3) THEN 1
                ELSE 0
           END
     ) AS totalTimeSecs

您可以通过将以下内容添加到选择表达式列表

来检测“异常”数据
, CASE WHEN SUM(CASE 
                WHEN t.status IN (1) THEN -1 
                WHEN t.status IN (2, 3) THEN 1 
                ELSE 0 END
              ) = 0 
       THEN 'OK' 
       ELSE 'ABNORMAL' 
   END AS integrityCheck

注意:任何“未闭合”的间隔都将被标记为异常;没有更复杂和昂贵的开始和结束检查间隔来区分“开放”和“无效”,它可能是最好的。 用于额外“integrityCheck”等于-1的总和可能暗示开放的结束时间间隔,但也可能表示错误的双重启动。