MySQL – Sum time ignoring seconds

[adsense id=”0514458240″ width=”468″ height=”60″]

I have seen this requested many times especially for reporting. Let’s imagine we need to generate a report which displays hours and minutes and a sum of the reported times. Imagine we have the following information in our database:

mysql> select starttime, endtime, diff, time_format(diff, '%H:%i') reportedtime from timer;
+-----------+----------+----------+--------------+
| starttime | endtime  | diff     | reportedtime |
+-----------+----------+----------+--------------+
| 09:09:53  | 17:05:23 | 07:55:30 | 07:55        | 
| 09:09:00  | 09:09:01 | 00:00:01 | 00:00        | 
| 09:09:00  | 09:09:30 | 00:00:30 | 00:00        | 
| 09:09:00  | 09:09:59 | 00:00:59 | 00:00        | 
| 09:00:00  | 09:00:30 | 00:00:30 | 00:00        | 
| 09:00:00  | 09:01:59 | 00:01:59 | 00:01        | 
| 09:00:00  | 09:01:00 | 00:01:00 | 00:01        | 
| 09:00:00  | 09:01:01 | 00:01:01 | 00:01        | 
+-----------+----------+----------+--------------+
8 rows in set (0.01 sec)

So far so good. By what if we perform a sum on the field “diff”.

mysql> select sec_to_time(sum(time_to_sec(diff))) from timer;
+-------------------------------------+
| sec_to_time(sum(time_to_sec(diff))) |
+-------------------------------------+
| 08:01:30                            | 
+-------------------------------------+
1 row in set (0.00 sec)

While this is accurate it does not match the reported hours and minutes:

mysql> select time_format(diff, '%H:%i') reportedtime from timer;
+--------------+
| reportedtime |
+--------------+
| 07:55        | 
| 00:00        | 
| 00:00        | 
| 00:00        | 
| 00:00        | 
| 00:01        | 
| 00:01        | 
| 00:01        | 
+--------------+
8 rows in set (0.00 sec)

As a result we need to round the content to the nearest minute before performing the calculation. In order to round there are several ways to perform this:

  • Using FLOOR(time / 60) * 60 which rounds the content down returning an integer
  • Using the (time DIV 60) * 60 operator which performs a division returning an integer

Here is an example of both operations:

mysql> SELECT Sec_to_time(Sum(Time_to_sec(diff)))                  accurate,
    ->        Sec_to_time(Sum(Time_to_sec(diff) DIV 60) * 60)      roundeddiv,
    ->        Sec_to_time(Sum(Floor(Time_to_sec(diff) / 60)) * 60) roundedfloor
    -> FROM   timer;  
+----------+------------+--------------+
| accurate | roundeddiv | roundedfloor |
+----------+------------+--------------+
| 08:01:30 | 07:58:00   | 07:58:00     | 
+----------+------------+--------------+
1 row in set (0.01 sec)