Search code examples
mysqlsqlmysql-error-1111

Calculating Total Overtime MySQL


I am creating a timeclock system and management website. I am trying to pull the amount of overtime for a particular department with a MySQL query.

The timeclocks update a MySQL table called events, which stores the employee_id, the job they are working on, the time_in and the time_out. I can produce a table of the total hours worked from each employee_id with:

SELECT employee_id, 
       SEC_TO_TIME(SUM(TIMEDIFF(time_out,time_in))) AS hours 
  FROM events 
 GROUP BY employee_id;

This will return a table of employee_ids and the total hours they worked. To create a table of employee_ids overtime I use:

SELECT employee_id,
       IF(HOUR(SEC_TO_TIME(SUM(TIMEDIFF(time_out,time_in))))>40,
          HOUR(SEC_TO_TIME(SUM(TIMEDIFF(time_out,time_in))))-40,
          0) AS overtime 
  FROM events 
  GROUP BY employee_id;

This returns a table of employee_ids and the amount of overtime they have worked.

The trouble I am having starts when I want to find a total of the overtime worked for all employees. I assumed I would be able to just put the IF function to find overtime inside of SUM() however when i run the following statement:

SELECT SUM(IF(HOUR(SEC_TO_TIME(SUM(TIMEDIFF(time_out,time_in))))>40,
              HOUR(SEC_TO_TIME(SUM(TIMEDIFF(time_out,time_in))))-40,
              0)) AS overtime 
 FROM events;

I get this error back:

ERROR 1111 (HY000): Invalid use of group function

I have looked all over for this but have found little in way of SUM(IF(SUM())) functions.

Note: The overtime has to be calculated individually, I cant just take total hours worked / number of employees - 40. If one worker works 30 hours in a week, and another works 50, there are 10 hours of overtime, but the average says there isn't any.


Solution

  • How about this?

    SELECT SUM(overtime)
      FROM
      (
        SELECT employee_id,
               IF(HOUR(SEC_TO_TIME(SUM(TIMEDIFF(time_out,time_in))))>40,
                  HOUR(SEC_TO_TIME(SUM(TIMEDIFF(time_out,time_in))))-40,
                  0) AS overtime 
          FROM events 
         GROUP BY employee_id
      )TOTAL
    

    When you're using SQL to implement complex business logic, nested queries have a key advantage: they let you test each level of the logic and build it up in a reliable way.