首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

Hr考勤计算有关问题-

2013-09-21 
Hr考勤计算问题-----急急急班次:EmpNoYYMMDDGO1OUT1GO2OUT2048901 2013-09-01NULLNULLNULLNULL048901 2013

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)
*/


[解决办法]
考勤问题千言万语估计都说不清楚,每个企业都不一样.

要解决这个问题,必须要从每个时间点,每个考勤对象去分析. 仅仅考虑迟到的情况.都有N个规则.

 例如 考勤系统中某员工A(技术部的工程师, 属于月薪人员)在2008-8-8日08:05 才来上班,本来上班时间08:00, 那么这个员工算不算迟到   

 第1步检查是否对该员工2008-8-8这一天作了特殊规则,如果这一天奥运会开幕,可以不计算迟到,那么该员工不算迟到,如果没有特殊规定   

 第2步检查是否对该员工有特别的规定,例如不计迟到,或者允许迟到10分钟,那么该员工就应该不算迟到, 如果没有特殊规定   
    
 第3步检查技术部的工程师是否有特殊规定,例如不计迟到,或者允许迟到10分钟,那么该员工就应该不算迟到, 如果没有特殊规定
    
 第4步检查技术部的月薪是否有特殊规定,例如不计迟到,或者允许迟到10分钟,那么该员工就应该不算迟到, 如果没有特殊规定
    
 第5步检查工程师是否有职位规定,例如不计迟到,或者允许迟到10分钟,那么该员工就应该不算迟到, 如果没有特殊规定   
    
 第6步检查技术部是否存在部门规定, 如果没有... 直到找到规定,
    
 第7步检查月薪人员是否存在规定,例如不计迟到,或者允许迟到10分钟,那么该员工就应该不算迟到, 如果没有特殊规定   

 第8步按整个公司的制度执行, 如果整个公司允许迟到5分钟,则不算迟到,否则按迟到处理。

如果要做一个通用的考勤系统, 估计处理一个员工一天的考勤存储过程都要写上万行. 
[解决办法]
感觉需求比较简单,实际情况会更复杂。
1、有没有夜班??难道只有白班??
2、最好定义一下上班前几个小时内打卡承认,定州下班后几个小时内打卡承认。
3、没有请假这种情况??
4、我们是工厂,所以还会有调班这种情况。
5、连续打多次卡怎么处理,如08:20打一次,08:50又打一次,算正常?还是算异常??
6、中午时间,如果12:15打一次,12:20又打一次,怎么计算??

我们的判断方式是一天中一个人一个人的判断。


1、在班次表中,取一天的全部工号,用循环一个人一个人的判断。
2、到打卡记录中,查出相应的打卡记录,按时间排序。
3、先判断上班1,按前3小时,后2小时找打卡记录。如果没有,按漏打算,如果有,判断正常或是迟到。然后在查询出来打卡记录中,去掉这条记录。
4、再判断下班1,按前2小时,后1小时查找打卡记录。如果没有,按漏打算,如果有,判断正常或是早退。然后在查询出来打卡记录中,去掉这条记录。
5、再判断上班2,按前1小时,后2小时找打卡记录。如果没有,按漏打算,如果有,判断正常或是迟到。然后在查询出来打卡记录中,去掉这条记录。
4、最后判断下班2,按前2小时,后3小时查找打卡记录。如果没有,按漏打算,如果有,判断正常或是早退。
最后统计一下结果就可以得到迟到、早退了。
加班就要根据打卡时间一点一点的算了(用临时表来保存班次的四个时间点和判断出来的打卡的四个时间点,这样就好计算加班时间)。

如果有请假、调班等情况,就需要通过判断来调整班次中的四个时间点,计算出应该上班和下班的正确时间。
[解决办法]
建议用程序来实现逻辑

我的方法:
1、规则说明
2、定义每人刷卡周期
3、定义每人刷卡次数
4、定义刷卡时间

现在无法上图,迟点再上几个图,看图就知道大概思路了

结果
Hr考勤计算有关问题-
Hr考勤计算有关问题-

热点排行