获取两个日期之间的9 AM-5PM之间的小时

时间:2019-03-25 06:36:20

标签: mysql sql

我有两个具有以下结构的表。

任务表

enter image description here

任务时间表

enter image description here

我想获取start_date_timeend_date_time之间的时间(天,小时和分钟)。上午9点至下午5点之间的时间为工作时间,应仅考虑进行计算。例如,如果start_date_time2019-03-25 09:00:00,而end_date_time2019-03-26 17:00:00,则计算时间将为2天。如果end_date_time2019-03-26 12:00:00,则计算的时间将是1天3小时。同一任务可以有多个时间条目,应该计算总时间。我已经尝试使用下面的查询来获取时间,但是它给出了总时间。我只想要9 AM到5 PM之间的时间。 DB Fiddle

SELECT t.task_name, sum(time_to_sec(timediff(end_date_time, start_date_time )) / 3600) FROM `task_time` tt left join task t on tt.task_id=t.task_id
group by tt.task_id

1 个答案:

答案 0 :(得分:2)

最简单的处理方法是分别计算天数和小时数,然后将一天算为8小时。像这样:

SELECT t.task_name, 
       SUM(TIMESTAMPDIFF(DAY, DATE(start_date_time), DATE(end_date_time)) * 8 +
           TIMESTAMPDIFF(MINUTE, TIME(start_date_time), TIME(end_date_time)) / 60) AS task_time
FROM task t
JOIN task_time tt ON tt.task_id = t.task_id
GROUP BY t.task_name

输出(用于我的演示数据)

task_name   task_time
task1       16
task2       11
task3       4

Demo on dbfiddle

更新

此查询将允许开始时间和结束时间在9 AM-5PM之外,而仅将9AM到5PM之间的小时数作为工作时间。通过使用GREATESTLEAST将开始时间和结束时间强制设置为9 AM-5PM:

SELECT t.task_name, 
       SUM(TIMESTAMPDIFF(DAY, start_date, end_date) * 8 +
           TIMESTAMPDIFF(MINUTE, TIME(start_time), TIME(end_time)) / 60) AS task_time
FROM task t
JOIN (SELECT task_id,
             DATE(start_date_time) AS start_date,
             DATE(end_date_time) AS end_date,
             GREATEST('09:00', LEAST('17:00', TIME(start_date_time))) AS start_time,
             GREATEST('09:00', LEAST('17:00', TIME(end_date_time))) AS end_time
      FROM task_time) tt ON tt.task_id = t.task_id
GROUP BY t.task_name

Updated demo

更新2

此查询返回的时间为天,小时和分钟,而不仅仅是小时。

SELECT t.task_name,
       days + FLOOR(minutes / 480) AS days,
       CASE WHEN minutes < 0 THEN 8 + FLOOR(minutes % 480 / 60)
            ELSE FLOOR(minutes % 480 / 60)
            END AS hours,
       CASE WHEN minutes < 0 THEN (60 + (minutes % 60)) % 60
            ELSE minutes % 60
            END AS minutes
FROM (SELECT t.task_name, 
             SUM(TIMESTAMPDIFF(DAY, start_date, end_date)) AS days,
             SUM(TIMESTAMPDIFF(MINUTE, TIME(start_time), TIME(end_time))) AS minutes
      FROM task t
      JOIN (SELECT task_id,
                   DATE(start_date_time) AS start_date,
                   DATE(end_date_time) AS end_date,
                   GREATEST('09:00', LEAST('17:00', TIME(start_date_time))) AS start_time,
                   GREATEST('09:00', LEAST('17:00', TIME(end_date_time))) AS end_time
            FROM task_time) tt ON tt.task_id = t.task_id
      GROUP BY t.task_name) t

Updated demo