MYSQL& PHP计算特定日期的总小时数并排除重叠小时数

时间:2014-05-31 23:44:43

标签: php mysql database select-query

我有一个MYSQL表,用于每个任务都有日期,开始时间,结束时间和user_id的任务。我想计算特定日期的总小时数。

表格结构

CREATE TABLE tasks
    (`id` int,`user_id` int, `title` varchar(30), `task_date` datetime, `start` time, `end` time)
;

INSERT INTO tasks
    (`id`,`user_id`, `title`,`task_date`, `start`, `end`)
VALUES
    (1,10, 'Task one','2013-04-02', '02:00:00', '04:00:00'),
    (2,10, 'Task two','2013-04-02', '03:00:00', '06:00:00'),
    (3,10, 'Task three.','2013-04-02','06:00:00', '07:00:00');

MYSQL查询

select  TIME_FORMAT(SEC_TO_TIME(sum(TIME_TO_SEC(TIMEDIFF( end, start)))), "%h:%i") AS diff
FROM tasks
where task_date="2013-04-02"

我得到的结果是“06:00”小时很好,但我想排除重叠小时。在示例中,我给出的结果应该是“05:00”小时,当第二条记录中的3-4小时被排除时,因为这小时已经存在于2-4之间的第一条记录中。

  • 第1条记录2 => 4 = 2小时
  • 第2记录3 => 6 = 3小时3-1小时= 2(1小时是第1和第2记录之间的重叠小时)
  • 3rd 6 => 7 = 1

总计5小时

我希望我明白我的问题。 示例 http://sqlfiddle.com/#!2/05dd8/2

1 个答案:

答案 0 :(得分:1)

这是一个使用变量的想法(在其他数据库中,CTE和窗口函数会使这变得更容易)。我们的想法是首先列出所有时间 - 开始和结束。然后,跟踪累计启动和停止次数。

当累计数大于0时,则包括与上一次的差异。如果等于0,则它是新时间段的开始,因此不添加任何内容。

以下是查询示例,通过不跟踪user_id中的更改来简化您的数据:

select user_id, TIME_FORMAT(SEC_TO_TIME(sum(secs)), '%h:%i')
from (select t.*, 
             @time := if(@sum = 0, 0, TIME_TO_SEC(TIMEDIFF(start, @prevtime))) as secs,
             @prevtime := start,
             @sum := @sum + isstart
      from ((select user_id, start, 1 as isstart
             from tasks t
            ) union all
            (select user_id, end, -1
             from tasks t
            )
           ) t cross join
           (select @sum := 0, @time := 0, @prevtime := 0) vars
      order by 1, 2
     ) t
group by user_id;

Here是一个SQL小提琴,显示它正常工作。