`

一个关于考勤统计的sql研究

sql 
阅读更多
     在这里,我们要做一个简单的员工考勤记录查询系统的后台数据库。业务需求如下所示:
     1.统计每天来的最早、来的最晚、走的最早、走得最晚的人的姓名
          1.1 统计每天来得最早的人的姓名和打卡时间
            步骤1:从考勤信息表中查询出每天来得最早的人的上班打卡时间和人员编号
     解决这个问题的时候本来考虑的是在考勤信息记录表中按照日期对考勤信息进行分组,然后取每组中上班时间(att_work_datatime)的最小值,但是后来几经折腾发现group by只能实现分组,而order by只能实现组外排序,因此这个方法只能放弃。再三考虑了一下,可以在分组之前先对表中att_work_datatime列中的所有值进行升序排序后生成一个临时表,然后对这个临时表中的att_work_datatime按照日期再分组,这样对att_work_datatime列按照日期group by之后取的就是每天上班打卡最早的人,我们从attendance_info_table(考勤信息表)表中查询出出每天上班时间最早的人的编号、上班时间和下班时间,sql语句如下: 
         select tmp.att_work_datatime,tmp.after_work_datatime,tmp.emp_id 
          from
          (select id,att_work_datatime,after_work_datatime,emp_id
                from attendance_info_table
                order by att_work_datatime) as tmp
           group by Date(att_work_datatime)
          执行查询结果如下:
          
          结果并不如愿,发现多了一行null值,才发现分组的时候mysql默认将null分为一组,这样就多了一组null数据。这样我们只需要在排序之前过滤掉  打卡时间为null的数据行,sql语句如下:
           select tmp.att_work_datatime,tmp.after_work_datatime,tmp.emp_id
            from
           (select id,att_work_datatime,after_work_datatime,emp_id
                from attendance_info_table
                 where att_work_datatime is not null
order by att_work_datatime) as tmp
     group by Date(att_work_datatime)
     查询出来的结果如下图所示:
     
     步骤2:从员工表和考勤信息表中联结查询出每天来得最早的人的姓名上班打卡时间    
      这样,还没有满足需求,我们要打印的是每天来得最早的人的姓名和上班打卡时间,由于员工的信息在另外一张表employee_info_table中放着,这样我们需要用到多表联结查询,根据雇员编号进行等值联结查询,sql语句如下所示:
     select em.emp_name,tmp.att_work_datatime
     from employee_info_table as em ,
     (select id,att_work_datatime,after_work_datatime,emp_id
          from attendance_info_table
          where att_work_datatime is not null
          order by att_work_datatime )
     as tmp
     where em.id=tmp.emp_id
     group by Date(att_work_datatime)
 
select eit.*, ait.att_work_datatime
from attendance_info_table ait, employee_info_table eit
where ait.emp_id = eit.id and ait.att_work_datatime in
     (select min(att_work_datatime)
       from attendance_info_table
        where att_work_datatime is not null
          group by Date(att_work_datatime))
order by ait.att_work_datatime asc;
     查询出来的结果如下图所示:
     
     OK,大功告成。在这里要说明的是,为了缩短sql语句并且为了在一条sql语句中多次使用相同的表,上面的查询中我们使用em 作为员工信息表employee_info_table 的表别名,使用tmp作为排序后生成的临时表的表别名。
     1.2 统计每天来得最晚的人的姓名和打卡时间
     步骤和2.1中统计每天来的最早的人的方法相同,唯一不同的是分组之前先对表中att_work_datatime列中的所有值进行降序排序,sql语句如下:
     select em.emp_name,tmp.att_work_datatime 
     from employee_info_table as em ,
     (select id,att_work_datatime,after_work_datatime,emp_id
          from attendance_info_table
          where att_work_datatime is not null
          order by att_work_datatime desc)
     as tmp
     where em.id=tmp.emp_id
     group by Date(att_work_datatime)
 
select eit.*, ait.att_work_datatime 
from attendance_info_table ait, employee_info_table eit
where ait.emp_id = eit.id and ait.att_work_datatime in
     (select max(att_work_datatime) 
     from attendance_info_table 
     where att_work_datatime is not null 
     group by Date(att_work_datatime))
order by ait.att_work_datatime asc;
     执行查询的结果如下:
     
 
      1.3 统计每天走得最早的人的姓名和打卡时间
             步骤和2.1中统计每天来的最早的人的方法相同,唯一不同的是对表中列中after_work_datatime的所有值进行升   序排序,并将查询的列由att_work_datatime改为after_work_datatime,sql语句如下:
          select em.emp_name,tmp.after_work_datatime 
          from employee_info_table as em ,
          (select id,att_work_datatime,after_work_datatime,emp_id
               from attendance_info_table
               where after_work_datatime is not null
               order by after_work_datatime)
          as tmp
          where em.id=tmp.emp_id
          group by Date(after_work_datatime)
 
select eit.*, ait.after_work_datatime 
from attendance_info_table ait, employee_info_table eit
where ait.emp_id = eit.id and ait.after_work_datatime in 
     (select min(after_work_datatime)
     from attendance_info_table
     where after_work_datatime is not null
     group by Date(after_work_datatime))
order by ait.after_work_datatime asc;
     查询结果如下:
          
 
      1.4 统计每天走得最晚的人的姓名和打卡时间
           步骤和2.2中统计每天来的最晚的人的方法相同,唯一不同的是对表中列中after_work_datatime的所有值进行降序排序,并将查询的列由att_work_datatime改为after_work_datatime,sql语句如下:
     select em.emp_name,tmp.after_work_datatime 
     from employee_info_table as em ,
     (select id,att_work_datatime,after_work_datatime,emp_id
          from attendance_info_table
          where after_work_datatime is not null
          order by after_work_datatime desc)
     as tmp
     where em.id=tmp.emp_id
     group by Date(after_work_datatime)
 
select eit.*, ait.after_work_datatime
from attendance_info_table ait, employee_info_table eit
where ait.emp_id = eit.id and ait.after_work_datatime in
     (select max(after_work_datatime)
     from attendance_info_table
     where after_work_datatime is not null
     group by Date(after_work_datatime))
order by ait.after_work_datatime asc;
     查询结果如下:
     
  
    2.统计每天工作时间最长、工作时间最短的人的姓名
      2.1统计每天工作时间最长的人的姓名
          步骤1:从考勤信息表中查询出每天工作时间最长的人的编号和工作时长
          解决这个问题,我们需要建立在问题1解决方法的基础上,我们先取出考勤信息表中上班打卡时间att_work_datatime、下班打卡时          间after_work_datatime、上下班打卡时间之差作为一天的工作时长att_time以及员工编号emp_id生成一个临时表tmp并将打卡时间为null的数据过滤掉,然后对tmp表中的att_time进行降序排 序然后根据日期进行分组,这样我们就可以从attendance_info_table(考勤信息表)表中查询出每天工作时间最长的人的编号和此人的工作时长。为了计算两个时间差,我们使用mysql自带的函数timediff(time1,time2)来计算time1-time2的时长。sql语句如下:
               select tmp.att_time,tmp.emp_id
               from
               (select id,att_work_datatime,after_work_datatime,timediff(after_work_datatime,att_work_datatime) as att_time,emp_id
                    from attendance_info_table
                    where att_work_datatime is not null and after_work_datatime is not null
                   order by att_time desc) as tmp
                 group by Date(att_work_datatime)
                  查询出的结果如下图所示:
                   
               步骤2:从考勤信息表和员工表中利用等值联结查询出每天工作时间最长的人的姓名和工作时长
               我们根据雇员编号进行等值联结查询出每天工作时间最长的人的姓名和工作时长,sql语句如下所示:
select eit.*,tmp.att_time, tmp.att_work_datatime
from employee_info_table eit,
     (select id,att_work_datatime,timediff(after_work_datatime,att_work_datatime) as att_time,emp_id
     from attendance_info_table
     where att_work_datatime is not null and after_work_datatime is not null) as tmp
where eit.id=tmp.emp_id and tmp.att_time in
(select max(timediff(after_work_datatime,att_work_datatime)) as att_time   
        from attendance_info_table
        where att_work_datatime is not null and after_work_datatime is not null
     group by date(att_work_datatime))
group by date(tmp.att_work_datatime)
order by att_work_datatime;
执行出的结果如下图所示:
            
      2.2统计每天工作时间最短的人的姓名
select eit.*,tmp.att_time, tmp.att_work_datatime
from employee_info_table eit,
     (select id,att_work_datatime,timediff(after_work_datatime,att_work_datatime) as att_time,emp_id
     from attendance_info_table
     where att_work_datatime is not null and after_work_datatime is not null) as tmp
where eit.id=tmp.emp_id and tmp.att_time in
(select min(timediff(after_work_datatime,att_work_datatime)) as att_time    
        from attendance_info_table
        where att_work_datatime is not null and after_work_datatime is not null
     group by date(att_work_datatime))
group by date(tmp.att_work_datatime)
order by att_work_datatime;
          执行结果如下所示:
          
     3.统计每天迟到的人数、早退的人数
     3.1统计每天迟到的人数
select date(att_work_datatime) as date,count(*)  as late_nums
from attendance_info_table
where timediff(time(att_work_datatime),'09:30:59') > 0 and att_work_datatime is not null
group by date(att_work_datatime)
     执行结果如下图所示:
     
      3.2统计每天早退的人数
select date(after_work_datatime) as date,count(*)  as leave_early_nums
from attendance_info_table
where after_work_datatime is not null
     and timediff(time(after_work_datatime),'18:00:00')<0
     or timediff(after_work_datatime,att_work_datatime)<'08:00:00'
group by date(after_work_datatime)      
执行结果如下图所示:
     
     4.统计每个月迟到的人按迟到次数降序排序
select eit.*, count(*) as late_nums
from attendance_info_table as ait,employee_info_table as eit
where ait.att_work_datatime is not null
     and timediff(time(ait.att_work_datatime),'09:30:59') > 0
     and ait.emp_id = eit.id   
group by emp_id
order by  late_nums desc;
          执行结果如下:
     
     5.统计出迟到的人并按姓名按升序排序,打印出迟到的时间
select eit.*,timediff(time(ait.att_work_datatime),'09:30:59') as lately_times,date(ait.att_work_datatime) as lately_date
from attendance_info_table as ait,employee_info_table as eit
where ait.att_work_datatime is not null
     and timediff(time(ait.att_work_datatime),'09:30:59') > 0
     and eit.id=ait.emp_id
order by eit.emp_name asc;
执行结果如下:
     6.公司规定:每迟到一次扣10块钱,每分钟扣1块钱,计算出每天迟到的人扣的钱和公司一天因为迟到扣的钱的总数
     6.1计算出每天迟到的人扣的钱
select eit.*,timediff(time(ait.att_work_datatime),'09:30:59') as lately_times,date(ait.att_work_datatime) as lately_date,(10+1*(TIME_TO_SEC(timediff(time(ait.att_work_datatime),'09:30:59')))/60) as '罚金(元)'
from attendance_info_table as ait,employee_info_table as eit
where ait.att_work_datatime is not null
     and timediff(time(ait.att_work_datatime),'09:30:59') > 0
     and eit.id=ait.emp_id
order by eit.emp_name asc
执行结果如下:
6.1计算出公司每天因为迟到所扣的钱
select tmp.lately_date,sum(tmp.fadefor)  as '总罚金(元)'
from
     (select eit.*,timediff(time(ait.att_work_datatime),'09:30:59') as lately_times,date(ait.att_work_datatime) as lately_date,(10+1*(TIME_TO_SEC(timediff(time(ait.att_work_datatime),'09:30:59')))/60) as fadefor
     from attendance_info_table as ait,employee_info_table as eit
     where ait.att_work_datatime is not null
          and timediff(time(ait.att_work_datatime),'09:30:59') > 0
          and eit.id=ait.emp_id
     order by eit.emp_name asc) as tmp
group by  tmp.lately_date
执行结果如下:
     7.统计出每个月每个人因为迟到扣多少钱,按扣的钱数降序排序列出名单
     步骤一:统计出每个人每天迟到的时间并计算每个人每天的罚金
               方法同6.1
        步骤二:根据人员编号进行分组,统计每个人每个月所扣的钱,并排序
select tmp.id,tmp.emp_name,sum(tmp.fadefor) as 'total_fadefor' from
     (select eit.*,(10+1*(TIME_TO_SEC(timediff(time(ait.att_work_datatime),'09:30:59')))/60) as 'fadefor'
     from attendance_info_table as ait,employee_info_table as eit
     where ait.att_work_datatime is not null
          and timediff(time(ait.att_work_datatime),'09:30:59') > 0
          and eit.id=ait.emp_id) as tmp
group by tmp.id
order by total_fadefor desc;    
          
           查询结果如下:
          
   8.列举出既没有迟到也没有早退记录的人的名单
     步骤一:统计出每个人每个月正常出勤的天数
select eit.*,count(*) as normal_nums
from attendance_info_table as ait,employee_info_table as eit
where ait.att_work_datatime is not null
     and ait.after_work_datatime is not null
     and timediff(time(ait.att_work_datatime),'09:30:59') < 0
     and timediff(after_work_datatime,att_work_datatime)>'08:00:00'
     and ait.emp_id = eit.id    
group by ait.emp_id
 
步骤2:查询出出勤次数大于指定天数的人的名单
select tmp.id,tmp.emp_name from
(select eit.*,count(*) as normal_nums
from attendance_info_table as ait,employee_info_table as eit
where ait.att_work_datatime is not null
     and ait.after_work_datatime is not null
     and timediff(time(ait.att_work_datatime),'09:30:59') < 0
     and timediff(after_work_datatime,att_work_datatime)>'08:00:00'
     and ait.emp_id = eit.id
group by ait.emp_id
)as tmp where tmp.normal_nums>=21 
步骤三:通过获取一个月的天数,查询出一个月每天都正常出勤的人的名单
select tmp.id,tmp.emp_name from
(select eit.*,count(*) as normal_nums
from attendance_info_table as ait,employee_info_table as eit
where ait.att_work_datatime is not null
     and ait.after_work_datatime is not null
     and timediff(time(ait.att_work_datatime),'09:30:59') < 0
     and timediff(after_work_datatime,att_work_datatime)>'08:00:00'
     and ait.emp_id = eit.id
group by ait.emp_id
)as tmp
where tmp.normal_nums>=
(select count(*)
     from
     (select date(att_work_datatime)  as date
     from attendance_info_table
     where att_work_datatime is not null
     group by date(att_work_datatime)) as tmp)
执行结果如下:
1
0
分享到:
评论
2 楼 asialee 2014-04-11  
shinyatime 写道
怎么图片显示不出来啊

我这边可以呀,是不是网速的问题,这个是从evernote里面直接复制过来的。
1 楼 shinyatime 2014-04-11  
怎么图片显示不出来啊

相关推荐

    VB+SQL考勤管理信息系统

    通过学习和研究这个案例,开发者不仅可以掌握VB和SQL的基础应用,还能了解到如何将二者结合,实现一个完整的管理信息系统。 总的来说,VB和SQL的结合使用为开发高效、稳定的考勤管理信息系统提供了可能。这个公路...

    yuan_gong_kao_qin.rar_delphi考勤统计实现_员工考勤_员工考勤系统_考勤系统

    本篇将详细介绍一个基于Delphi开发的小型员工考勤统计系统,它的设计与实现,以及如何在现有基础上进行扩展。 Delphi是一款强大的Windows应用开发工具,以其高效的编译器和丰富的组件库著称。在本考勤系统中,...

    关于考勤管理系统中的SQL语句优化解析.pdf

    考勤管理系统的SQL语句优化是针对数据库性能的一个重要方面,涉及到对大量数据的处理和查询性能的提升。在给定的文档内容中,针对沙钢集团人力资源管理信息系统月初汇总上一月考勤数据时所遇到的效率问题,通过多种...

    考勤系统 net sql server.rar

    总的来说,"考勤系统 Net SQL Server"不仅是一个实用的软件产品,也是一个优秀的学习资源,无论你是.NET开发者,还是对Web开发感兴趣的初学者,都能从中受益匪浅。通过深入研究这个项目,你可以提升自己的编程技能,...

    这是一个Python 中的学生考勤管理系统(SAMS),使用Tkinter、SQL、Opencv进行面部识别考勤记录.zip

    总结来说,"Python 中的学生考勤管理系统(SAMS)"是一个集成了Tkinter GUI设计、SQL数据库管理和OpenCV面部识别的综合性项目,它在提高学校考勤管理效率的同时,也为我们提供了一个多技术融合的学习典范。...

    VB考勤管理系统论文

    《VB考勤管理系统论文》是针对企业或机构日常考勤管理需求而设计的一份技术性研究文档。在当今信息化社会,高效、准确的考勤管理是确保组织运行有序、提升工作效率的重要环节。VB(Visual Basic)作为Microsoft公司...

    vb+sql职工考勤管理系统职工考勤管理系统下载(论文+系统+开题报告).zip

    通过SQL查询,系统可以快速地获取特定时间段内的考勤统计报告,帮助管理层进行决策。 3. **职工考勤管理**:这个系统的核心功能是记录和分析员工的出勤情况。它包括但不限于以下子功能: - **打卡管理**:记录员工...

    vb+sql职工考勤管理系统职工考勤管理系统(论文+系统+开题报告).rar

    【标题】"vb+sql职工考勤管理系统职工考勤管理系统(论文+系统+开题报告).rar" 提供了一个基于VB编程语言与SQL数据库技术构建的职工考勤管理系统的完整项目资源,包括了系统设计的理论研究、实际开发以及项目开题的...

    vb+sql职工考勤管理系统职工考勤管理系统(设计说明书+系统+调研报告).zip

    《VB+SQL职工考勤管理系统》是一个基于Visual Basic(VB)编程语言和SQL数据库技术的考勤管理软件。这个系统的主要目标是实现对企事业单位职工的出勤情况进行有效管理,包括记录员工的上下班时间、迟到、早退、请假...

    毕业论文jsp1320教师考勤sqlserver.doc

    本毕业论文旨在设计并实现一个基于Web技术的教师考勤管理系统,该系统将采用B/S架构,前端使用JSP进行开发,后端利用SqlServer作为数据库管理系统。系统的目的是提供一个用户友好的界面,方便教师的日常考勤记录,...

    vb+sql职工考勤管理系统职工考勤管理系统(论文+系统+开题报告).zip

    这是一个针对企业或组织内部员工出勤情况进行管理和记录的系统,旨在提高工作效率,简化考勤统计工作。 【描述】:“vb+sql职工考勤管理系统职工考勤管理系统(论文+系统+开题报告).zip” 描述中的信息表明,这个...

    人事管理系统——考勤系统论文

    综上所述,《人事管理系统——考勤系统论文》将深入剖析如何利用VB和SQL技术,构建一个既满足日常考勤管理需求,又能为企业决策提供数据支持的人事考勤系统。这个系统不仅可以提高企业的管理水平,也能提升员工的...

    vb+sql职工考勤管理系统职工考勤管理系统(论文+系统+开题报告)_计算机毕业设计源代码.rar

    《VB+SQL职工考勤管理系统》是一个典型的计算机毕业设计项目,它综合运用了Visual Basic(VB)编程语言和SQL数据库技术,旨在实现企业或机构的员工考勤管理自动化。这个系统包括了完整的论文、系统软件以及开题报告...

    PHP+SQL考勤系统安全性实现源码 - 保护企业考勤数据安全

    系统功能包括员工考勤记录、请假管理、加班统计、报表生成等。特别强调安全性,采用加密技术和多重身份验证机制,保护数据不被未授权访问。用户界面友好,操作简便,后台管理高效。源码提供完整的功能实现,便于学习...

    vb+sql职工考勤管理系统职工考勤管理系统(论文+系统+开题报告)【VB】.zip

    《VB+SQL职工考勤管理系统》是一个基于Visual Basic(VB)编程语言和SQL数据库技术的管理软件,主要用于记录和管理企业或机构内部员工的出勤情况。该系统集成了考勤记录、统计分析、异常提醒等多种功能,为人力资源...

    员工考勤系统

    4. **报表生成**:系统应具备生成各类考勤报表的功能,如月度考勤汇总、部门考勤统计、异常考勤报告等,以帮助管理层进行决策。 5. **权限控制**:不同的用户角色(如管理员、员工、部门经理)可能有不同的操作权限...

Global site tag (gtag.js) - Google Analytics