考勤問題思路和解決
阿新 • • 發佈:2017-07-23
信息 har job 工作日 end con object post rda
插入測試數據
我的思路是用一張暫時表得到這個月的全部工作日。將該暫時表與用戶進行交叉連接。這樣每一個用戶在這個月的每一個工作日都有一條記錄。
從原始的kaoqin表中查詢出每一個用戶的上班時間和下班時間。假設用戶一天的打開記錄超過兩條。那麽就會取最早和最晚的一條分別作為上班時間和下班時間。
通過暫時表#tempUserDate和上面的查詢結果關聯,假設左聯接為空,則證明該人員缺勤。
以下是遲到和早退的實現SQL。
得到的結果
近期在做一個考勤系統,考勤主要關註的是缺勤、遲到和早退。眼下的打卡控制器能夠記錄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定期存儲每年的節日,假設員工請假,也須要納入到系統的考慮中。
考勤問題思路和解決