首页 » 技术分享 » 考勤统计,一张表查询每月的员工考勤数据

考勤统计,一张表查询每月的员工考勤数据

 

近期根据公司人事要求,写了一些关于考勤统计的报表。主要是查询员工每月的考勤数据,要求一行数据显示员工的当月的每天的考勤信息,标的样式如下:

然后,根据考勤表,写了如下SQL语句,来实现报表的查询,谨以此做记录,以备后续查阅。

SELECT DeptName                  AS 所属部门,
       UserName                  AS 员工姓名,
       UserKQID                  AS 员工编号,
       Substring(WorkDate, 1, 7) AS 考勤月份,
       Count(( CASE
                 WHEN isworkday = 1
                      AND ( Datediff(minute, BeginTime, endtime) ) / 60 >= 9 THEN WorkDate
               END ))            AS 正常出勤天数,
       Count(( CASE
                 WHEN ( isworkday = 1
                        AND BeginTime = EndTime
                        AND BeginTime > '12:00:00' )
                       OR ( isworkday = 1
                            AND BeginTime = EndTime
                            AND EndTime < '12:00:00' )
                       OR ( isworkday = 1
                            AND BeginTime IS NULL
                            AND EndTime IS NULL ) THEN WorkDate
               END ))            AS 异常出勤天数,
       Count(( CASE
                 WHEN ( isworkday = 1
                        AND BeginTime = EndTime
                        AND BeginTime > '12:00:00' ) THEN WorkDate
               END ))            AS 上班未打卡,
       Count(( CASE
                 WHEN ( isworkday = 1
                        AND BeginTime = EndTime
                        AND EndTime < '12:00:00' ) THEN WorkDate
               END ))            AS 下班未打卡,
       Count(( CASE
                 WHEN ( isworkday = 1
                        AND BeginTime IS NULL
                        AND EndTime IS NULL ) THEN WorkDate
               END ))            AS 上下班未打卡,
       Count(( CASE
                 WHEN isworkday = 1
                      AND BeginTime > '08:30:00'
                      AND BeginTime <= '08:40:00' THEN WorkDate
               END ))            AS 迟到小于十分钟,
       Count(( CASE
                 WHEN isworkday = 1
                      AND BeginTime > '08:40:00' THEN WorkDate
               END ))            AS 迟到大于十分钟,
       Count(( CASE
                 WHEN isworkday = 1
                      AND BeginTime IS NOT NULL
                      AND EndTime IS NOT NULL
                      AND BeginTime <> EndTime
                      AND 540 - Isnull(( Datediff(minute, BeginTime, endtime) ), 0) <= 10
                      AND 540 - Isnull(( Datediff(minute, BeginTime, endtime) ), 0) > 0 THEN WorkDate
               END ))            AS 早退小于十分钟,
       Count(( CASE
                 WHEN isworkday = 1
                      AND BeginTime IS NOT NULL
                      AND EndTime IS NOT NULL
                      AND BeginTime <> EndTime
                      AND 540 - Isnull(( Datediff(minute, BeginTime, endtime) ), 0) > 10 THEN WorkDate
               END ))            AS 早退大于十分钟,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '01' THEN BeginTime
             END ))              AS 上班1,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '01' THEN endtime
             END ))              AS 下班1,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '01' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长1,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '02' THEN BeginTime
             END ))              AS 上班2,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '02' THEN endtime
             END ))              AS 下班2,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '02' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长2,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '03' THEN BeginTime
             END ))              AS 上班3,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '03' THEN endtime
             END ))              AS 下班3,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '03' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长3,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '04' THEN BeginTime
             END ))              AS 上班4,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '04' THEN endtime
             END ))              AS 下班4,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '04' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长4,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '05' THEN BeginTime
             END ))              AS 上班5,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '05' THEN endtime
             END ))              AS 下班5,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '05' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长5,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '06' THEN BeginTime
             END ))              AS 上班6,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '06' THEN endtime
             END ))              AS 下班6,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '06' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长6,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '07' THEN BeginTime
             END ))              AS 上班7,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '07' THEN endtime
             END ))              AS 下班7,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '07' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长7,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '08' THEN BeginTime
             END ))              AS 上班8,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '08' THEN endtime
             END ))              AS 下班8,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '08' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长8,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '09' THEN BeginTime
             END ))              AS 上班9,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '09' THEN endtime
             END ))              AS 下班9,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '09' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长9,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '10' THEN BeginTime
             END ))              AS 上班10,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '10' THEN endtime
             END ))              AS 下班10,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '10' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长10,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '11' THEN BeginTime
             END ))              AS 上班11,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '11' THEN endtime
             END ))              AS 下班11,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '11' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长11,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '12' THEN BeginTime
             END ))              AS 上班12,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '12' THEN endtime
             END ))              AS 下班12,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '12' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长12,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '13' THEN BeginTime
             END ))              AS 上班13,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '13' THEN endtime
             END ))              AS 下班13,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '13' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长13,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '14' THEN BeginTime
             END ))              AS 上班14,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '14' THEN endtime
             END ))              AS 下班14,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '14' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长14,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '15' THEN BeginTime
             END ))              AS 上班15,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '15' THEN endtime
             END ))              AS 下班15,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '15' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长15,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '16' THEN BeginTime
             END ))              AS 上班16,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '16' THEN endtime
             END ))              AS 下班16,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '16' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长16,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '17' THEN BeginTime
             END ))              AS 上班17,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '17' THEN endtime
             END ))              AS 下班17,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '17' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长17,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '18' THEN BeginTime
             END ))              AS 上班18,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '18' THEN endtime
             END ))              AS 下班18,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '18' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长18,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '19' THEN BeginTime
             END ))              AS 上班19,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '19' THEN endtime
             END ))              AS 下班19,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '19' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长19,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '20' THEN BeginTime
             END ))              AS 上班20,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '20' THEN endtime
             END ))              AS 下班20,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '20' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长20,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '21' THEN BeginTime
             END ))              AS 上班21,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '21' THEN endtime
             END ))              AS 下班21,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '21' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长21,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '22' THEN BeginTime
             END ))              AS 上班22,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '22' THEN endtime
             END ))              AS 下班22,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '22' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长22,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '23' THEN BeginTime
             END ))              AS 上班23,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '23' THEN endtime
             END ))              AS 下班23,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '23' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长23,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '24' THEN BeginTime
             END ))              AS 上班24,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '24' THEN endtime
             END ))              AS 下班24,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '24' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长24,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '25' THEN BeginTime
             END ))              AS 上班25,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '25' THEN endtime
             END ))              AS 下班25,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '25' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长25,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '26' THEN BeginTime
             END ))              AS 上班26,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '26' THEN endtime
             END ))              AS 下班26,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '26' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长26,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '27' THEN BeginTime
             END ))              AS 上班27,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '27' THEN endtime
             END ))              AS 下班27,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '27' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长27,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '28' THEN BeginTime
             END ))              AS 上班28,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '28' THEN endtime
             END ))              AS 下班28,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '28' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长28,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '29' THEN BeginTime
             END ))              AS 上班29,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '29' THEN endtime
             END ))              AS 下班29,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '29' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长29,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '30' THEN BeginTime
             END ))              AS 上班30,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '30' THEN endtime
             END ))              AS 下班30,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '30' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长30,
       Min(( CASE
               WHEN Substring(WorkDate, 9, 2) = '31' THEN BeginTime
             END ))              AS 上班31,
       Max(( CASE
               WHEN Substring(WorkDate, 9, 2) = '31' THEN endtime
             END ))              AS 下班31,
       Sum(( CASE
               WHEN Substring(WorkDate, 9, 2) = '31' THEN ( Datediff(minute, BeginTime, endtime) ) / 60
             END ))              AS 工作时长31
FROM   dbo.UserSignList
GROUP  BY DeptName,
          UserName,
          UserKQID,
          Substring(WorkDate, 1, 7) 

由于数据量可能会很大,公司的考勤数据后续做了分表处理,以及中间表处理。初步思路是根据中间表获取数据,新建一张中间表,把员工的考勤数据稍作处理,按照员工姓名、年份、月份分组,然后查询每和员工每月的考勤数据时,中间表的数据中,每个员工,每月数据仅有一条,查询的数量级非常小,速度也很快。至于中间表的设计,后续会有新的文章发出来,供大家参考,交流。

先看看查询的效果

转载自原文链接, 如需删除请联系管理员。

原文链接:考勤统计,一张表查询每月的员工考勤数据,转载请注明来源!

0