考勤查询统计SQL脚本。

本文主要记录下平时工作中考勤统计中的SQL脚本,以便于后续翻阅,同时和大家分享一下,不足的地方还请大牛多多给与点评。 

1.首先是查询某员工的考勤记录。可以根据年份,月份,或者时间段查询结果,同时也可以去掉人员筛选条件,查询多个人的考勤结果。以及计算出该员工的打卡是否正常。SQL语句如下所示: 


SELECT 员工号,卡号,姓名,日期,
       '打卡记录'  AS 考勤类型,
       Substring(日期, 1, 4)   AS 年份,
       Substring(日期, 6, 2)   AS 月份,
       Datename(weekday, 日期) AS 工作日类型,
       Min(打卡时间)             AS 上班打卡时间,
       Max(打卡时间)             AS 下班打卡时间,
       CASE
         WHEN Datename(weekday, 日期) <> '星期六'
              AND Datename(weekday, 日期) <> '星期日' THEN( CASE
                                                         WHEN Min(打卡时间) = Max(打卡时间) THEN'上班或下班忘打卡'
                                                         WHEN Min(打卡时间) > '08:00:00' THEN '迟到'
                                                         WHEN Max(打卡时间) < '17:00:00' THEN '早退'
                                                         ELSE '正常'
                                                       END )
         ELSE '非工作日打卡'
       END                   AS 状态
FROM   (SELECT a.[emp_id]                        员工号,
               a.[card_id]                       卡号,
               b.[emp_fname]                     姓名,
               CONVERT(CHAR(10), sign_time, 120) 日期,
               CONVERT(VARCHAR, sign_time, 108)  打卡时间,
               [sign_time]
        FROM   [dbo].[TimeRecords] a
               LEFT JOIN [dbo].[Employee] b
                      ON a.emp_id = b.emp_id
                         AND a.[card_id] = b.[card_id]
        WHERE  a.emp_id IS NOT NULL
               AND a.emp_id <> ''
               AND CONVERT(CHAR(10), sign_time, 120) BETWEEN '2018-09-01' AND '2018-10-30'
               AND b.[emp_fname] = '姓名') AS mm
GROUP  BY mm.员工号,
          卡号,
          姓名,
          mm.日期
ORDER  BY 员工号,
          日期 ASC 

查询结构如下所示:

查询结果

2.根据部门,员工姓名、日期查询员工的打卡记录:

SELECT a.emp_fname,
       b.depart_name,
       CONVERT(CHAR(10), sign_time, 120)                    date,
       Min(c.sign_time)                                     AS BeginTime,
       Max(c.sign_time)                                     AS EndTime
	   Datediff(minute, Min(c.sign_time), Max(c.sign_time)) AS minute,
FROM   Employee a
       LEFT JOIN Departs b
              ON a.depart_id = b.depart_id
       LEFT JOIN TimeRecords c
              ON a.emp_id = c.emp_id
WHERE  Substring(a.depart_id, 1, 3) = '041'
       AND CONVERT(CHAR(10), sign_time, 120) BETWEEN '2018-11-01' AND '2018-11-30'
       AND a.emp_id IS NOT NULL
GROUP  BY depart_name,
          emp_fname,
          CONVERT(CHAR(10), sign_time, 120)
ORDER  BY depart_name,
          emp_fname,
          CONVERT(CHAR(10), sign_time, 120) ASC

查询结果如下所示:

3.统计某一时间段内的员工的上下班打卡次数,以及迟到或早退30分钟以内的和30分钟以上的数据。

SELECT a.emp_fname,
       b.depart_name,
       CONVERT(CHAR(10), sign_time, 120)                    date,
       Min(c.sign_time)                                     AS BeginTime,
       Max(c.sign_time)                                     AS EndTime
	   Datediff(minute, Min(c.sign_time), Max(c.sign_time)) AS minute,
FROM   Employee a
       LEFT JOIN Departs b
              ON a.depart_id = b.depart_id
       LEFT JOIN TimeRecords c
              ON a.emp_id = c.emp_id
WHERE  Substring(a.depart_id, 1, 3) = '041'
       AND CONVERT(CHAR(10), sign_time, 120) BETWEEN '2018-11-01' AND '2018-11-30'
       AND a.emp_id IS NOT NULL
GROUP  BY depart_name,
          emp_fname,
          CONVERT(CHAR(10), sign_time, 120)
ORDER  BY depart_name,
          emp_fname,
          CONVERT(CHAR(10), sign_time, 120) ASC
SELECT b.emp_fname,
       b.depart_name,
       Sum(CASE
             WHEN ms = 0
                  AND CONVERT(CHAR(10), EndTime, 23) < '12:00:00' THEN 1
             ELSE 0
           END) AS 上班未打卡,
       Sum(CASE
             WHEN ms = 0
                  AND CONVERT(CHAR(10), EndTime, 23) > '12:00:00' THEN 1
             ELSE 0
           END) AS 下班未打卡,
       Sum(CASE
             WHEN 540 - ms BETWEEN 0 AND 30 THEN 1
             ELSE 0
           END) AS 迟到或早退30分钟以内,
       Sum(CASE
             WHEN 540 - ms > 30 THEN 1
             ELSE 0
           END) AS 迟到或早退30分钟以上
FROM   (SELECT TOP 100 PERCENT a.emp_fname,
                               b.depart_name,
                               Min(c.sign_time)                                     AS BeginTime,
                               Max(c.sign_time)                                     AS EndTime,
                               Datediff(minute, Min(c.sign_time), Max(c.sign_time)) AS ms
        FROM   Employee a
               LEFT JOIN Departs b
                      ON a.depart_id = b.depart_id
               LEFT JOIN TimeRecords c
                      ON a.emp_id = c.emp_id
        WHERE  Substring(a.depart_id, 1, 3) = '041'
               AND CONVERT(CHAR(10), sign_time, 120) BETWEEN '2018-11-01' AND '2018-11-30'
               AND a.emp_id IS NOT NULL
        GROUP  BY depart_name,
                  emp_fname,
                  CONVERT(CHAR(10), sign_time, 120)
        ORDER  BY depart_name,
                  emp_fname,
                  CONVERT(CHAR(10), sign_time, 120) ASC) AS b
GROUP  BY emp_fname,
          depart_name
ORDER  BY depart_name,
          emp_fname 

查询结果如下: 

4.统计各种假期的请假时长 :

/****** Script for SelectTopNRows command from SSMS  ******/
SELECT applyUser,
       ApplyDept,
       Sum(CASE
             WHEN leavetype = '事假' THEN leaveHours
             ELSE 0
           END) AS 事假,
       Sum(CASE
             WHEN leavetype = '病假' THEN leaveHours
             ELSE 0
           END) AS 病假,
       Sum(CASE
             WHEN leavetype = '产检假' THEN leaveHours
             ELSE 0
           END) AS 产前病事假,
       Sum(CASE
             WHEN leavetype = '产假'
                   OR LeaveType = '陪产假' THEN leaveHours
             ELSE 0
           END) AS 产假或护理假,
       Sum(CASE
             WHEN leavetype = '婚假' THEN leaveHours
             ELSE 0
           END) AS 婚假,
       Sum(CASE
             WHEN leavetype = '丧假' THEN leaveHours
             ELSE 0
           END) AS 丧假,
       Sum(CASE
             WHEN leavetype = '年休假' THEN leaveHours
             ELSE 0
           END) AS 年假,
       Sum(CASE
             WHEN leavetype = '公假' THEN leaveHours
             ELSE 0
           END) AS 公假,
       Sum(CASE
             WHEN leavetype = '其他' THEN leaveHours
             ELSE 0
           END) AS 其他,
       Sum(CASE
             WHEN leavetype = '调休' THEN leaveHours
             ELSE 0
           END) AS 调休,
       Sum(CASE
             WHEN leavetype = '工伤假' THEN leaveHours
             ELSE 0
           END) AS 工伤假
FROM   HR_Leave
WHERE  CompanyId = 16
       AND Node = 2
	   AND CONVERT(CHAR(10), Start, 120) BETWEEN '2018-09-01' AND '2018-12-30'
GROUP  BY ApplyDept,
          ApplyUserId,
          ApplyUser 

SQL执行结果如下所示:

 5.根据加班类型,统计各种加班类型的加班时长:

/****** Script for SelectTopNRows command from SSMS  ******/
SELECT [ApplyUser],
       [ApplyDept],
       Sum(CASE
             WHEN [OtType] = '平时延长' THEN Duration
             ELSE 0
           END) AS 平时延长,
       Sum(CASE
             WHEN [OtType] = '休息日' THEN Duration
             ELSE 0
           END) AS 休息日,
       Sum(CASE
             WHEN [OtType] = '法定节假日' THEN Duration
             ELSE 0
           END) AS 法定节假日
FROM   HR_Overtime
WHERE  CompanyId = 16
       AND Node = 2
	   AND CONVERT(CHAR(10), CreateDateTime, 120) BETWEEN '2018-09-01' AND '2018-12-30'
GROUP  BY [ApplyDept],
          ApplyUserId,
          [ApplyUser] 

查询结果如下所示:

后续持续更新包含请假、加班、出差等相关联的综合查询。注:请假、出差、加班等流程在其他数据库中,几者关联查询不太想用DBLink,所以只有单独查询出来,在代码中用Linq做关联查询,关于跨数据库的关联查询,如果哪位老师有好的建议,欢迎留言。谢谢!

猜你喜欢

转载自blog.csdn.net/shenjqiang/article/details/84559788