1

我正在研究一种复杂的 mysql 查询来计算员工在某一天的总工作时间。它适用于某些员工,但不适用于其他员工。我已经创建了一个 SQL Fiddle,所以你可以很容易地看到我在说什么。 http://sqlfiddle.com/#!2/6439f/1/0

数据:

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

询问:

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

结果:

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

Roxanne 的第一个结果应该是返回时间,它返回 NULL。Jeffery 的第二个工作正常。布鲁斯的第三个是返回时间,但我计算的时间是错误的。有谁知道这里发生了什么?谢谢迈克

4

4 回答 4

1

作为世界上最丑陋的查询的参赛者......

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`

通过在您的 SQLFiddle 上运行它,我获得了以下结果:

姓名打卡日期 SEC_TO_TIME(SUM(U.DELTA))
布鲁斯·科尔曼 06-17-2013 10:11:09
杰弗里·波特 06-17-2013 09:00:13
罗克珊尼森 06-17-2013 09:29:42

对应于每天工作的分钟数。

请注意,应该在白天处理任意数量的突破。这不适用于夜间工作的人(即白天入住,第二天退房)。

于 2013-06-25T16:13:59.413 回答
0

对于 Roxanne,核心 SQL 是这样的:

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'
于 2013-06-25T15:45:57.540 回答
0

+----------------+------------+----------------- +--------------+----------+
| 姓名 | 打卡日期 | 工作时间 | 工作时间 | 工作小时数小数 |
+----------------+------------+----------------- +--------------+----------+
| 罗克珊尼森 | 06-17-2013 | 空 | 92982 | 380974.9583 |
| 杰弗里·波特 | 06-17-2013 | 09:00:13 | 90013 | 380974.4992 |
| 布鲁斯·科尔曼 | 06-17-2013 | 10:51:49 | 105149 | 761945.2653 | +----------------+------------+----------------- +--------------+----------+

3 行,5 个警告(0.00 秒)

mysql> 显示警告;+---------+------+-------------------------------- -------------+
| 水平 | 代码 | 留言 |
+---------+------+-------------------------------- -------------+
| 警告 | 第1292章 不正确的日期时间值:'-20130617072748' |
| 警告 | 第1292章 不正确的日期时间值:'-20130617072944' |
| 警告 | 第1292章 不正确的日期时间值:'-20130617062048' |
| 警告 | 第1292章 不正确的日期时间值:'-20130617124358' |
| 警告 | 第1292章 截断不正确的时间值:'92982' |
+---------+------+-------------------------------- -------------+ 5 行(0.00 秒)

抱歉格式错误

于 2013-06-25T15:49:03.380 回答
0

查看您的数据,您的查询在我看来是不可能的。也许可以使用子查询,但如果是我,我会在应用程序中计算它。如果您的签到和签出时间戳在相同的记录中,那么它会容易得多。但是插入这样的事件意味着首先插入打卡,然后用打卡时间更新相同的记录。

在当前布局中,您可以为每个员工选择特定日期的事件并计算小时数。确保您订购了活动,并且您处理了无论出于何种原因而缺少打卡和打卡事件的情况。

最后一部分我不明白你怎么能在 SQL 语句中做。

更新:我现在看到你关于 In-Out 的想法,但实际上这并不是失败的证明。一个不错的技巧 - 是的,但不是我依赖的东西。

于 2013-06-25T15:33:58.603 回答