简体   繁体   中英

MySQL query returning incorrect results

I am working on a kind of complicated mysql query to calculate total hours worked for an employee in a given day. It will work correctly for some employees, but not for others. I have created a SQL Fiddle so you can easily see what I am talking about. http://sqlfiddle.com/#!2/6439f/1/0

Data:

CREATE TABLE punches 
(
     PunchID int auto_increment primary key, 
     EmpID varchar(6),
     Name varchar(20), 
     PunchDateTime DateTime,
     PunchEvent varchar(20),
     `In-Out` int
);    

INSERT INTO punches
(EmpID, Name, PunchDateTime, PunchEvent, `In-Out`)
VALUES
('0538', 'ROXANNE NIESEN', '2013-06-17 07:27:48', 'clockin', 1),
('0538', 'ROXANNE NIESEN', '2013-06-17 16:57:30', 'clockout', 0),
('1102', 'JEFFERY POTTER', '2013-06-17 07:29:44', 'clockin', 1),
('1102', 'JEFFERY POTTER', '2013-06-17 16:29:57', 'clockout', 0),
('1588', 'BRUCE COLEMAN', '2013-06-17 06:20:48', 'clockin', 1),
('1588', 'BRUCE COLEMAN', '2013-06-17 12:15:18', 'breakout', 0),
('1588', 'BRUCE COLEMAN', '2013-06-17 12:43:58', 'breakin', 1),
('1588', 'BRUCE COLEMAN', '2013-06-17 17:00:37', 'clockout', 0);

Query:

SELECT Name, DATE_FORMAT(p.PunchDateTime, '%m-%d-%Y') AS 'Punch Date',
TIME(SUM(p.PunchDateTime * (1 - 2 * `p`.`In-Out`))) AS 'Hours Worked Time',
SUM(p.PunchDateTime * (1 - 2 * `p`.`In-Out`)) AS 'Hours Worked',
SUM(UNIX_TIMESTAMP(p.PunchDateTime*(1-2*`p`.`In-Out`)))/3600 AS 'Hours Worked Decimal'
FROM punches p
WHERE DATE(p.PunchDateTime) = '2013-06-17'
GROUP BY DATE(p.PunchDateTime), EmpID

Result:

|           NAME | PUNCH DATE |              HOURS WORKED TIME | HOURS WORKED | HOURS WORKED DECIMAL |
------------------------------------------------------------------------------------------------------
| ROXANNE NIESEN | 06-17-2013 |                         (null) |        92982 |          380968.9583 |
| JEFFERY POTTER | 06-17-2013 | January, 01 1970 09:00:13+0000 |        90013 |          380968.4992 |
|  BRUCE COLEMAN | 06-17-2013 | January, 01 1970 10:51:49+0000 |       105149 |          761933.2653 |

The first result with Roxanne should be returning time and it returns NULL. The second with Jeffery is working correctly. And the third with Bruce is returning time, but the time is wrong when I did the math. Does anyone know what is going on here? Thanks Mike

As a contestant for the ugliest query in the world ....

SELECT U.Name, U.`Punch Date`, SEC_TO_TIME(SUM(U.delta)) FROM
(
(
SELECT `enter`.Name, `enter`.PunchDateTime AS `time`,
DATE_FORMAT(`enter`.PunchDateTime, '%m-%d-%Y') AS 'Punch Date',
TIMESTAMPDIFF(SECOND, `enter`.PunchDateTime, '2003-05-01 00:00:00') AS `delta`


FROM Punches AS `enter`
WHERE `enter`.`In-Out` = 1
)
UNION
(
SELECT `leave`.Name, `leave`.PunchDateTime AS `time`,
DATE_FORMAT(`leave`.PunchDateTime, '%m-%d-%Y') AS 'Punch Date',
-TIMESTAMPDIFF(SECOND, `leave`.PunchDateTime, '2003-05-01 00:00:00') AS `delta`


FROM Punches AS `leave`
WHERE `leave`.`In-Out` = 0  
)
) AS U
GROUP BY U.Name,U.`Punch Date`

By running that on your SQLFiddle, I obtain the following results:

NAME    PUNCH DATE  SEC_TO_TIME(SUM(U.DELTA))
BRUCE COLEMAN   06-17-2013  10:11:09
JEFFERY POTTER  06-17-2013  09:00:13
ROXANNE NIESEN  06-17-2013  09:29:42

Corresponding to the number of minutes worked each day.

Please notice that should handle any number of breakout during the day. That does not handle people working at night (that is check-in on day, check-out the next day).

Looking at your data, your query looks to me impossible. Perhaps doable with a subquery but if it was me I'd have it calculated in the applicaiton. If your clockin and clockout timestamps are in same reord, then it would be a LOT easier. But inserting such events would mean first insert the clockin and later update same record with the clockout time.

In current layout , for each employee you can SELECT events in particular days and calculate the hours. Make sure you order events and that you handle the case where clockin and clockout events are missing for whatever reason.

The last part I don't see how could you do in an SQL statement.

UPDATE: I see now your idea about In-Out, but really that's not failure proof. A nice hack - yeah, but not something I'd rely on.

For Roxanne, the core SQL is something like this:

SELECT p.EmpID, (p1.PunchDateTime - p.PunchDateTime) AS t
FROM punches p left join punches p1 on p.EmpID = p1.EmpID
WHERE p.PunchEvent = 'clockin' and p1.PunchEvent = 'clockout'
AND p.EmpID = '0538'

+----------------+------------+-------------------+--------------+----------------------+
| Name | Punch Date | Hours Worked Time | Hours Worked | Hours Worked Decimal |
+----------------+------------+-------------------+--------------+----------------------+
| ROXANNE NIESEN | 06-17-2013 | NULL | 92982 | 380974.9583 |
| JEFFERY POTTER | 06-17-2013 | 09:00:13 | 90013 | 380974.4992 |
| BRUCE COLEMAN | 06-17-2013 | 10:51:49 | 105149 | 761945.2653 | +----------------+------------+-------------------+--------------+----------------------+

3 rows in set, 5 warnings (0.00 sec)

mysql> SHOW WARNINGS; +---------+------+---------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------+
| Warning | 1292 | Incorrect datetime value: '-20130617072748' |
| Warning | 1292 | Incorrect datetime value: '-20130617072944' |
| Warning | 1292 | Incorrect datetime value: '-20130617062048' |
| Warning | 1292 | Incorrect datetime value: '-20130617124358' |
| Warning | 1292 | Truncated incorrect time value: '92982' |
+---------+------+---------------------------------------------+ 5 rows in set (0.00 sec)

Sorry for the bad formatting

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM