Вычисление разницы между строками даты и времени между строками в одной таблице

0

У меня есть таблица, в которой хранятся записи с задачами, статусом и временем срабатывания:

Таблица 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
    «Расчет для A правильный, B - неправильный». Не должно ли значение mytimedifference для задачи A составлять 3600 секунд (1 час) вместо 7200 секунд (2 часа)? ... начало 2018-03-07 20:00:00 конец 2018-03-07 21:30:00 минус 30 минут перерыва.
  • 0
    Не совсем уверен, какой должна быть релевантность идентификатора; B никогда не ассоциируется с id = 3 в исходных данных.
Показать ещё 3 комментария
Теги:
datetime
time
datediff

1 ответ

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

Примечание: любые "незамкнутые" интервалы будут отмечены как ненормальные; без более сложной и дорогостоящей проверки начала и конца интервалов, чтобы дифференцировать "открытые" с "недействительными", это, вероятно, лучшее, что можно сделать. Сумма, используемая для дополнительной проверки целостности, равная -1, может намекать на открытый интервал, но также может указывать на ошибочное двойное начало.

  • 0
    хм ... не работает правильно, если taks содержит все три статуса. См. Калькуляцию для D sqlfiddle.com/#!9/050a41/1
  • 0
    D выглядит как неверные данные для меня; у него есть «начало», «пауза», «остановка», но отсутствует «возобновление» после «паузы».
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню