查询mysql一天工作总时间的最佳方法
我正试图找到一种最好的方法来计算员工上班的总时间 冲床类型为每日冲床、休息冲床、休息冲床和休息冲床。你可能会认为我可以选择*where date=date,但如果员工在晚上11:30到达,第二天凌晨2:00离开,那就不行了 我在想这样的事情可能是最好的解决方案,但我不知道这是否可行: 从上次记录中选择*,其中employee=员工在第一次“打卡”时停止 这将收集自该员工上次打卡以来的所有信息。例如: ID名称类型时间 45约翰日 46乔一天的时间 玛丽休息时间到了 48乔出发时间 49乔磨合时间 每天外出50小时 玛丽准时到达 52乔白天休息时间 53玛丽白天外出时间 所以在我想的例子中,如果你在寻找Joe的时间,它会从PunchID53开始向后搜索,直到找到Punch46。结果将是冲头46、48、49和51。然后我可以计算出工作的总时间。再说一遍,我不知道这是否可能查询mysql一天工作总时间的最佳方法,mysql,math,time,Mysql,Math,Time,我正试图找到一种最好的方法来计算员工上班的总时间 冲床类型为每日冲床、休息冲床、休息冲床和休息冲床。你可能会认为我可以选择*where date=date,但如果员工在晚上11:30到达,第二天凌晨2:00离开,那就不行了 我在想这样的事情可能是最好的解决方案,但我不知道这是否可行: 从上次记录中选择*,其中employee=员工在第一次“打卡”时停止 这将收集自该员工上次打卡以来的所有信息。例如: ID名称类型时间 45约翰日 46乔一天的时间 玛丽休息时间到了 48乔出发时间 49乔磨合时间
我非常感谢您对如何实现这一目标提出的任何意见/建议,或任何其他更实际的方法 将问题分解为多个步骤,首先列出所有“IN”记录:
SELECT p_in.*
FROM punches p_in
WHERE p_in.type = 'IN'
接下来,编写一个子查询以查找下一个“OUT”记录(为了简单起见,此方法假设id是自动递增的):
现在,将此查询包装在一个类似于Punchs表的外部选择中:
SELECT pb.id, pb.name, pb.type, pb.time
FROM punches pb
WHERE pb.id = (
SELECT MIN(pa.id)
FROM punches pa
WHERE pa.type = 'OUT'
AND pa.name = p_in.name
AND pa.time > p_in.time
)
并在与原始查询的左联接中使用:
SELECT
p_in.id in_id,
p_in.name in_name,
p_in.type in_type,
p_in.time in_time,
p_out.id out_id,
p_out.name out_name,
p_out.type out_type,
p_out.time out_time
FROM punches p_in
LEFT JOIN (
SELECT pb.id, pb.name, pb.type, pb.time
FROM punches pb
WHERE pb.id = (
SELECT MIN(pa.id)
FROM punches pa
WHERE pa.type = 'OUT'
AND pa.name = p_in.name
AND pa.time > p_in.time
)
) p_out
WHERE p_in.type = 'IN'
这将为您提供一个结果集,其中每个“in”记录都有下一个对应的“out”记录。如果没有相应的out记录,out值将设置为null
希望您可以使用这些结果来计算您需要的信息。您已经有了员工Id、打卡类型Id,但是您缺少了日期或时段Id,这将使事情变得更简单: PunchId PeriodId Employee PunchTypeId PunchDateTime -------- --------- --------- ------------ -------------- ... 44 1 Mary Day In TIME 45 1 John Day In TIME 46 1 Joe Day In TIME 47 1 Mary Break Out TIME 48 1 Joe Break Out TIME 49 1 Joe Break In TIME 50 1 John Day Out TIME 51 1 Mary Break In TIME 52 1 Joe Day Out TIME 53 1 Mary Day Out TIME 54 2 John Day In TIME 55 2 Mary Day In TIME 56 2 Joe Day In TIME ...
这是假设在一个PeriodId内,所有员工每人有四次打孔(每天打孔、休息、休息和休息)。此外,当打卡时间跨越日边界时,PeriodId不应与处理问题中提到的案例的日期绑定。相反,在插入该期间的最后一个打孔(即,日外打孔)后,增加员工的PeriodId。我将使用如下查询:
select workerid, sum(case
when punchtype = 'in' then -DATEDIFF(MINUTE, '20110901', punchtime)
when punchtype = 'out' then DATEDIFF(MINUTE, '20110901', punchtime)
when punchtype = 'bin' then -DATEDIFF(MINUTE, '20110901', punchtime)
when punchtype = 'bout' then DATEDIFF(MINUTE, '20110901', punchtime)
end )/60 as WorkingHours
from Punchlog
group by workerid
备注:
假设我有一张桌子:
create table PunchLog
(workerid int not null,
punchtime datetime not null,
punchtype char(4) not null)
用几天的打孔数据
让我们放置一些测试数据:
insert into PunchLog (workerid, punchtime, punchtype) values (1, '20110901 23:30', 'in')
insert into PunchLog (workerid, punchtime, punchtype) values (1, '20110902 03:30', 'out')
insert into PunchLog (workerid, punchtime, punchtype) values (1, '20110902 00:15', 'bin')
insert into PunchLog (workerid, punchtime, punchtype) values (1, '20110902 01:15', 'bout')
insert into PunchLog (workerid, punchtime, punchtype) values (2, '20110901 09:30', 'in')
insert into PunchLog (workerid, punchtime, punchtype) values (2, '20110901 17:00', 'out')
insert into PunchLog (workerid, punchtime, punchtype) values (2, '20110901 14:30', 'bin')
insert into PunchLog (workerid, punchtime, punchtype) values (2, '20110901 10:00', 'bout')
人员在工作场所花费的时间为:
T = out - in - (bin -bout) = out - in -bin + bout
其中,in
,out
是日打卡时间,bin
,bout
是中断打卡时间
如果我将按workerid
分组,并将sum()应用于punchtime
,则我将有工作时间,但我需要中的,而bin
时间为负值。我也不能计算日期时间。因此,我将punchtime
更改为从过去的任何日期开始,并使用用例语句设置符号:
sum(case
when punchtype = 'in' then -DATEDIFF(MINUTE, '20110901', punchtime)
when punchtype = 'out' then DATEDIFF(MINUTE, '20110901', punchtime)
. . .
end )/60 as WorkingHours
在我的测试中,它会产生以下结果:
workerid WorkingHours
-------- ------------
1 5
2 3
如果数据库的结构有所不同,那就更好了。当有人打卡时,你会记录下来,当有人打卡时,你会找到他们最近的打卡时间,并在其中添加一个打卡时间。但我认为这超出了你的控制范围,或者它有不同的理由以这种方式构建。我同意@Jefromi。更改数据库的结构将使系统更易于使用。这也使得人们更容易发现忘记打卡的情况。虽然这可能不在你的控制之下。我会以任何需要的方式重组它。。。这就是为什么我要求任何其他建议。什么是最好的???@user971230:我不是数据库设计专家,我也不知道你的所有要求,但如果你的主要要求是知道人们在那里呆了多久,那么我在第一条评论中建议的结构是一个合理的起点。它会更简单,但我需要跟踪是休息还是休息。我需要能够查看员工是否在白天或休息时被打卡。PS-这是我问题的一部分-我如何找到最近的打卡?哇。。。这看起来很神奇,但我很难理解。mysql字段是“punch_id”(自动递增)、“emp_id”(员工id)、punch_类型、punch_时间(时间戳)。我试图更新我的PHP页面以使用您提供的代码,但是您的示例中的名称让我有点困惑。您能建议如何使用我提供的字段名来执行此操作吗?我将不胜感激!这可能导致的一个问题是,一天中可能不会有四次打孔。员工不得休息。不过,我会仔细研究一下,谢谢你的建议。周期ID的想法让我思考。。。
sum(case
when punchtype = 'in' then -DATEDIFF(MINUTE, '20110901', punchtime)
when punchtype = 'out' then DATEDIFF(MINUTE, '20110901', punchtime)
. . .
end )/60 as WorkingHours
workerid WorkingHours
-------- ------------
1 5
2 3