考勤问题思路和解决

近期在做一个考勤系统,考勤主要关注的是缺勤、迟到和早退。眼下的打卡控制器能够记录username和打卡时间,用户可能一天打卡多次,也可能一天仅仅打了一次卡,这些情况都须要考虑。

打卡信息都存储在考勤表中,从中要挖掘出一个月内的缺勤人员,迟到人员和早退人员,而且能显示缺勤、迟到和早退的时间。

考勤表

CREATE TABLE [dbo].[kaoqin](
	[user_name] [varchar](50) NULL,
	[card_time] [datetime] NULL
) ON [PRIMARY]

GO

插入測试数据

INSERT INTO [master].[dbo].[kaoqin]
select '张三', '2014-08-03 09:36:00'
union all
select '张三', '2014-08-03 18:10:00'
union all
select '张三', '2014-08-04 08:32:00'
union all
select '张三', '2014-08-04 15:15:00'
union all
select '张三', '2014-08-05 09:32:00'
union all
select '张三', '2014-08-05 15:15:00'
union all
select '张三', '2014-08-01 08:36:00'
union all
select '张三', '2014-08-01 18:10:00'
union all
select '张三', '2014-08-02 08:32:00'
union all
select '张三', '2014-08-02 18:15:00'
union all
select '张三', '2014-08-25 08:00:00'
union all
select '张三', '2014-08-24 19:00:00'
union all
select '张三', '2014-08-27 08:00:00'
union all
select '张三', '2014-08-27 17:00:00'
union all
select '张三', '2014-08-26 10:00:00'
union all
select '张三', '2014-08-26 18:30:00'
union all
select '张三', '2014-08-26 8:00:00'
union all
select '张三', '2014-08-27 18:56:00'

GO

我的思路是用一张暂时表得到这个月的全部工作日。将该暂时表与用户进行交叉连接。这样每一个用户在这个月的每一个工作日都有一条记录。

如果早上9点为上班时间,18点为下班时间,这个能够兴许做成变量的形式。

declare @time_start datetime
declare	@time_end datetime 

set @time_start = '2014-08-01 00:00:00'
set @time_end = DATEADD(M,1,@time_start)

-- 一个月的工作日
IF object_id('tempdb..#tempDate') is not null
BEGIN
	drop table #tempDate
END
CREATE table #tempDate
(
	stat_day varchar(10)
)

IF object_id('tempdb..#tempUserDate') is not null
BEGIN
	drop table #tempUserDate
END
CREATE table #tempUserDate
(	

	stat_day varchar(10),
	[user_name] varchar(40)
)
CREATE clustered index tempUserDate_Index1 on #tempUserDate ([user_name],stat_day)

declare @time_temp datetime
set @time_temp = @time_start
while @time_temp < @time_end
begin
   if datepart(weekday,@time_temp)>1 and datepart(weekday,@time_temp)<7
   begin
	   insert into #tempDate (stat_day) values (CONVERT(varchar(10),@time_temp,121))
   end
   set @time_temp= dateadd(d,1,@time_temp)
end

insert into #tempUserDate
select * from #tempDate  cross join
(select distinct [user_name] from [kaoqin]) t

从原始的kaoqin表中查询出每一个用户的上班时间和下班时间。假设用户一天的打开记录超过两条。那么就会取最早和最晚的一条分别作为上班时间和下班时间。

select [user_name],CONVERT(varchar(10),card_time,121) as stat_day,
    MIN(card_time) as on_time,MAX(card_time) as off_time from [kaoqin]
    group by [user_name],CONVERT(varchar(10),card_time,121)

通过暂时表#tempUserDate和上面的查询结果关联,假设左联接为空,则证明该人员缺勤。

--缺勤
select * from #tempUserDate a
left join
(
    select [user_name],CONVERT(varchar(10),card_time,121) as stat_day,
    MIN(card_time) as on_time,MAX(card_time) as off_time from [kaoqin]
    group by [user_name],CONVERT(varchar(10),card_time,121)
) b on a.[user_name]=b.[user_name] and a.stat_day=b.stat_day
where [b].[user_name] is null

以下是迟到和早退的实现SQL。

--迟到
select * from #tempUserDate a
left join
(
    select [user_name],CONVERT(varchar(10),card_time,121) as stat_day,
    MIN(card_time) as on_time,MAX(card_time) as off_time from [kaoqin]
    group by [user_name],CONVERT(varchar(10),card_time,121)
) b on a.[user_name]=b.[user_name] and a.stat_day=b.stat_day
where CONVERT(varchar(100), [b].[on_time], 8)>'09:00:00'

--早退
select * from #tempUserDate a
left join
(
    select [user_name],CONVERT(varchar(10),card_time,121) as stat_day,
    MIN(card_time) as on_time,MAX(card_time) as off_time from [kaoqin]
    group by [user_name],CONVERT(varchar(10),card_time,121)
) b on a.[user_name]=b.[user_name] and a.stat_day=b.stat_day
where CONVERT(varchar(100), [b].[off_time], 8)<'18:00:00'

得到的结果

假设某个人他今天既迟到又早退在终于的结果中都会体现。能够从2014-08-05这条数据看出。当然,这个考勤系统还不完好,比如没有将节日考虑进来,初步的考虑是採用Job定期存储每年的节日,假设员工请假,也须要纳入到系统的考虑中。

时间: 2024-08-02 14:49:26

考勤问题思路和解决的相关文章

光缆故障排查思路及解决方式

第一个问题:光缆的区别?1.外观2.传输距离3.波长4.芯径    第二个问题:两台交换机如何通过光缆进行互联?1.光缆(明确光缆的类型.长度)1.交换机2.光模块(明确光模块的类型.速率)3.光纤跳线 (明确跳线的类型.长度.速率)5.耦合器(明确耦合器的类型)6.尾纤(明确跳线的类型.长度.速率)7.光纤配线架或者光纤终端盒(明确具体的类型)第三个问题:上述两台交换机之间无法通信?1.交换机的带电状态---->交换机接口故障--->替换法2.接口状态-->down3.检查模块--&g

三个思路解决413 Request Entity Too Large报错处理

最近一个项目当中,要求上传图片,并且限制图片大小,虽然在laravel当中已经添加了相关的表单验证来阻止文件过大的上传,然而当提交表单时,还没轮到laravel处理,nginx就先报错了.当你仔细看报错页面时,你会发现有nginx版本信息,经过分析,这报错是因为nginx的默认上传文件大小配置client_max_body_size只有2MB, 基于nginx验证比laravel验证要早,想要友好报错而不是直接显示413 Request Entity Too Large,那么就有三个思路去解决.

基于人脸识别的登陆认证方案及思路

本文主要讨论基于人脸识别的登陆认证过程中的关键技术点,讨论如何实现这些关键技术点并解决困难问题. 1.关键技术点及思路 (1)登陆认证在服务器端实现还是在客户端实现? 换句话说,人脸识别的模型应该运行在服务器端还是客户端.如果人脸识别模型运行在服务器端,那么客户端必须在联网环境下才能通过服务端的认证并使用.某些场景下,例如音乐客户端场景(用户在无需联网的情况下也需要进入APP听音乐),人脸识别模型运行在服务器就无法满足需求.如果人脸识别模型运行在客户端,那么需要模型足够简单,客户端能够提供运行模

javascript解决for循环中i取值的问题(转载)

html: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script type="text/javascript"> //面试经典问题: function onMyLoad(){ /* 抛出问题: 此题的目的是想每次点击对应目标时弹出对应的数字下标

解决UITableView在editing状态下点击任意一行(cell)依旧会触发TableViewCell所绑定的segue 的方法

继续总结 自己在第一个app中遇到的一些小问题 背景条件如下:现有一个prototype cell通过segue(show)与其DetailView相连,此UITableView包含编辑按钮(触发进入编辑editing状态) 如图二,在编辑状态下,假设用户准备选择多个cell进行删除,在用户的finger刚点击任意一个cell时,就已经触发了segue,进入到DetailView中,当通过NV Controller返回时,之前选择的cell当然还在 我所想要的是,在编辑状态下,阻止segue(类

Pig、Hive、MapReduce 解决分组 Top K 问题(转)

问题: 有如下数据文件 city.txt (id, city, value) cat city.txt 1 wh 5002 bj 6003 wh 1004 sh 4005 wh 2006 bj 1007 sh 2008 bj 3009 sh 900需要按 city 分组聚合,然后从每组数据中取出前两条value最大的记录. 1.这是实际业务中经常会遇到的 group TopK 问题,下面来看看 pig 如何解决: 1 a = load '/data/city.txt'  using PigSto

虚拟机克隆网卡启动失败的解决方法

本人虚拟机装的是Centos6.9版本. 需要装多台linux.为了方便,选择在此版本上克隆. 克隆后ifconfig查看网卡是eth1(系统启动时自动添加的),重启网卡失败. 考虑是网卡的MAC.UID和克隆本体重复了.修改网卡配置文件(ifcfg-eth0),删除UID和MAC项,暂时解决. 在给克隆机添加多块网卡的时候,重启网卡失败. 分析原因是因为一个网卡时,网卡配置文件没有MAC和UID,系统会自动加载唯一的网卡设备. 多块网卡时,由于网卡不是唯一的,在配置文件中不指明网卡设备的UID

支付宝soa框架发展思路(转载)

大家好,这里是首届QCon Beijing的现场,现在坐在我的旁边是的支付宝的首席架构师程立.先给大家介绍一下,支付宝架构发展到今天,经历哪些时期,都有哪些里程碑? 我回忆一下,支付宝系统架构发展大概有这么几点.我本人大概是2004年下半年参与支付宝系统建设的.当时的目标,支付宝系统是面向整个互联网,而不是淘宝网内部的一个产品.那应该说是支付宝系统的一个起点,那当时非常的简单,就是一个应用程序,提供了我们所有的功能.功能也不多,有我们基本的支付功能,还有清算的功能,基本的会员管理功能,包括后台管

用面向对象的方式解决经典的“三月兔”的问题

这是一个经典问题:有一对兔子,从出生后第三个月开始,每个月都生一对兔子,然后生出来的兔子也从出生第三个月开始每个月生一对兔子,假如兔子都不死,问每个月兔子总数是多少. 这个问题其实是一个斐波纳切数列,主要考虑递归的用法,这道题的"标准答案"就是用递归的方式来解决: 然而,这么做其实并不是按面向对象的思路来解决的.这是先画出表格,然后找出数字的排列规律,然后再写公式. 对于这种问题,我还是喜欢用面向对象的思路来解决它. 如果要以面向对象的思路来做,应该写一个兔子的对象,然后根据它的繁殖规