Hr考勤计算问题-----急急急
班次:
EmpNo YYMMDD GO1 OUT1 GO2 OUT2
048901 2013-09-01 NULL NULL NULL NULL
048901 2013-09-02 08:30 12:00 13:00 17:30
048901 2013-09-04 08:40 12:10 13:10 17:40
048901 2013-09-05 08:40 12:10 13:10 17:40
打卡记录:
EmpNo CardTime
048901 2013-09-02 08:25
048901 2013-09-02 08:29
048901 2013-09-02 12:12
048901 2013-09-02 12:28
048901 2013-09-02 17:28
048901 2013-09-02 17:35
048901 2013-09-03 08:30
048901 2013-09-03 12:15
048901 2013-09-03 12:50
048901 2013-09-03 17:45
048901 2013-09-04 08:35
048901 2013-09-04 12:35
048901 2013-09-04 12:50
048901 2013-09-04 17:45
048901 2013-09-05 08:35
048901 2013-09-05 12:35
048901 2013-09-05 12:50
048901 2013-09-05 17:45
048901 2013-09-05 17:56
048901 2013-09-05 21:05
打卡记录10分钟内取第一条记录,如果在班次中间(12:00-13:00)只有一条打卡记录,打卡记录离班次哪个时间点较近算哪个班次点的打卡记录。如有迟到、早退优先算作迟到或早退卡。
班次时间为null、没有当天的排班或者在班次外的打卡均算休息时间,考勤结果均算为加班(无排班情况下(周末或者节假日)加班一天最多只能算8小时,有排班(平时)一天最多只能算3小时加班)
最后需要能算出:
1、是否考勤异常;
2、迟到xx分钟
3、早退xx分钟
4、考勤工时:xx小时
5、加班时长:xx小时
根据以上规则得到的结果为:
员工[048901]2013-09-02考勤异常;早退2分钟;迟到0分钟;考勤工时:7.96小时;加班时长:0小时
员工[048901]2013-09-03考勤正常;早退0分钟;迟到0分钟;考勤工时:0.00小时;加班时长:8小时
员工[048901]2013-09-04考勤正常;早退0分钟;迟到0分钟;考勤工时:8.00小时;加班时长:0小时
员工[048901]2013-09-05考勤正常;早退0分钟;迟到0分钟;考勤工时:8.00小时;加班时长:3小时
以上问题可以用MS SQL存储过程计算也可以用java计算,能提供一些思路也好 考勤计算、打卡记录 ms?sql java 存储
[解决办法]
建议分步骤完成,
select * from 班次
/*
EmpNo YYMMDD GO1 OUT1 GO2 OUT2
---------- --------------- ---------- ---------- ---------- ----------
048901 2013-09-01 NULL NULL NULL NULL
048901 2013-09-02 08:30 12:00 13:00 17:30
048901 2013-09-03 08:30 12:00 13:00 17:30
048901 2013-09-04 08:40 12:10 13:10 17:40
048901 2013-09-05 08:40 12:10 13:10 17:40
(5 row(s) affected)
*/
select * from 打卡记录
/*
EmpNo CardTime
---------- ------------------------------
048901 2013-09-02 08:25
048901 2013-09-02 08:29
048901 2013-09-02 12:12
048901 2013-09-02 12:28
048901 2013-09-02 17:28
048901 2013-09-02 17:35
048901 2013-09-03 08:30
048901 2013-09-03 12:15
048901 2013-09-03 12:50
048901 2013-09-03 17:45
048901 2013-09-04 08:35
048901 2013-09-04 12:35
048901 2013-09-04 12:50
048901 2013-09-04 17:45
048901 2013-09-05 08:35
048901 2013-09-05 12:35
048901 2013-09-05 12:50
048901 2013-09-05 17:45
048901 2013-09-05 17:56
048901 2013-09-05 21:05
(20 row(s) affected)
*/
select EmpNo,
cast(YYMMDD as date) 'CardDate',
cast(YYMMDD+' '+GO1 as datetime) 'GO1',
cast(YYMMDD+' '+OUT1 as datetime) 'OUT1',
cast(YYMMDD+' '+GO2 as datetime) 'GO2',
cast(YYMMDD+' '+OUT2 as datetime) 'OUT2'
into #t1
from 班次
where GO1 is not null and OUT1 is not null
and GO2 is not null and OUT2 is not null
;with t as
(select EmpNo,
cast(CardTime as date) 'CardDate',
cast(CardTime as datetime) 'CardTime',
row_number() over(partition by cast(CardTime as date) order by cast(CardTime as datetime)) 'rn'
from 打卡记录)
select a.EmpNo,a.CardDate,a.CardTime,row_number() over(partition by a.CardDate order by a.CardTime) 'rn'
into #t2
from t a
left join t b on a.EmpNo=b.EmpNo and a.CardDate=b.CardDate and a.rn=b.rn+1
where datediff(mi,b.CardTime,a.CardTime)>10 or b.rn is null
select a.EmpNo,a.CardDate,
(select case when datediff(mi,b.CardTime,a.OUT1)>0 then datediff(mi,b.CardTime,a.OUT1) else 0 end
from #t2 b
where b.EmpNo=a.EmpNo and b.CardDate=a.CardDate and b.rn=2)+
(select case when datediff(mi,b.CardTime,a.OUT2)>0 then datediff(mi,b.CardTime,a.OUT2) else 0 end
from #t2 b
where b.EmpNo=a.EmpNo and b.CardDate=a.CardDate and b.rn=4) 'leaveearly',
(select case when datediff(mi,a.GO1,b.CardTime)>0 then datediff(mi,a.GO1,b.CardTime) else 0 end
from #t2 b
where b.EmpNo=a.EmpNo and b.CardDate=a.CardDate and b.rn=1)+
(select case when datediff(mi,a.GO2,b.CardTime)>0 then datediff(mi,a.GO2,b.CardTime) else 0 end
from #t2 b
where b.EmpNo=a.EmpNo and b.CardDate=a.CardDate and b.rn=3) 'late',
datediff(mi,a.OUT2,(select top 1 b.CardTime
from #t2 b where b.EmpNo=a.EmpNo and b.CardDate=a.CardDate order by b.rn desc))/60 'ot'
into #t3
from #t1 a
select '员工['+a.EmpNo+']'+convert(varchar,a.CardDate,23)+'考勤'
+case when a.leaveearly=0 and a.late=0 then '正常;' else '异常;' end
+'早退'+rtrim(a.leaveearly)+'分钟;'
+'迟到'+rtrim(a.late)+'分钟;'
+'考勤工时'+rtrim(convert(decimal(4,2),(8*60-a.leaveearly-a.late)/60.00))+'小时;'
+'加班时长'+rtrim(a.ot)+'小时' 'r'
from #t3 a
/*
r
---------------------------------------------
员工[048901]2013-09-02考勤异常;早退2分钟;迟到0分钟;考勤工时7.97小时;加班时长0小时
员工[048901]2013-09-03考勤正常;早退0分钟;迟到0分钟;考勤工时8.00小时;加班时长0小时
员工[048901]2013-09-04考勤正常;早退0分钟;迟到0分钟;考勤工时8.00小时;加班时长0小时
员工[048901]2013-09-05考勤正常;早退0分钟;迟到0分钟;考勤工时8.00小时;加班时长3小时
(4 row(s) affected)
*/
1、在班次表中,取一天的全部工号,用循环一个人一个人的判断。
2、到打卡记录中,查出相应的打卡记录,按时间排序。
3、先判断上班1,按前3小时,后2小时找打卡记录。如果没有,按漏打算,如果有,判断正常或是迟到。然后在查询出来打卡记录中,去掉这条记录。
4、再判断下班1,按前2小时,后1小时查找打卡记录。如果没有,按漏打算,如果有,判断正常或是早退。然后在查询出来打卡记录中,去掉这条记录。
5、再判断上班2,按前1小时,后2小时找打卡记录。如果没有,按漏打算,如果有,判断正常或是迟到。然后在查询出来打卡记录中,去掉这条记录。
4、最后判断下班2,按前2小时,后3小时查找打卡记录。如果没有,按漏打算,如果有,判断正常或是早退。
最后统计一下结果就可以得到迟到、早退了。
加班就要根据打卡时间一点一点的算了(用临时表来保存班次的四个时间点和判断出来的打卡的四个时间点,这样就好计算加班时间)。
如果有请假、调班等情况,就需要通过判断来调整班次中的四个时间点,计算出应该上班和下班的正确时间。
[解决办法]
建议用程序来实现逻辑
我的方法:
1、规则说明
2、定义每人刷卡周期
3、定义每人刷卡次数
4、定义刷卡时间
现在无法上图,迟点再上几个图,看图就知道大概思路了
结果