Получите часы между 9 утра-5 вечера между двумя датами - PullRequest
0 голосов
/ 25 марта 2019

У меня есть две таблицы со структурой ниже.

Таблица задач

enter image description here

Расписание задач

enter image description here

Я хочу получить время между start_date_time и end_date_time в днях, часах и минутах. Время между 9 утра-5 вечера - рабочие часы и должно учитываться только для расчета. Например, если start_date_time равно 2019-03-25 09:00:00 и end_date_time равно 2019-03-26 17:00:00, рассчитанное время составит 2 дня. Если end_date_time равно 2019-03-26 12:00:00, то расчетное время составит 1 день 3 часа. Одна и та же задача может иметь несколько записей времени, и общее время должно быть рассчитано. Я попытался с помощью запроса ниже, чтобы получить время, но оно дает общее количество часов. Я хочу только часы с 9 утра до 5 вечера. 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 Ответ

2 голосов
/ 25 марта 2019

Самый простой способ справиться с этим - рассчитать дни и часы отдельно, а затем просто считать день как 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

Демонстрация на dbfiddle

Обновление

В этом запросе время начала и окончания будет вне 9:00 - 17:00, а рабочие часы будут считаться только с 9:00 до 17:00. Он работает путем принудительного задания времени начала и окончания в диапазоне 9–5 вечера, используя GREATEST и LEAST:

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

Обновленная демоверсия

Обновление 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

Обновленная демоверсия

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...