Author: admin

  • 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)