to Yang_(扬帆破浪): INSERT INTO 不是重要,主要是处理打卡数据,怎么样提高运行效率。 找不到一个好的方法。
测试下以下笨方法的速度如何(特别注意:我直接删除了OriginalData标的数据,如果这时你的原始表,需要保存数据的,请用个临时表,并倒入OriginalData标的所有数据)update a set OnDuty1=(select top 1 checktime from OriginalData where EmployeeID=a.EmployeeID and CheckTime>=a.CheckDate and CheckTime<dateadd(day,1,a.CheckDate)), OnDuty4=(select top 1 checktime from OriginalData where EmployeeID=a.EmployeeID and CheckTime>=dateadd(day,1,a.CheckDate) and CheckTime<dateadd(day,2,a.CheckDate)) from OnOffDutyData adelete a from OriginalData a where not exists ( select 1 from OriginalData where EmployeeID=a.EmployeeID and convert(Nchar(10),CheckTime,120)=convert(Nchar(10),a.CheckTime,120) and CheckTime<a.CheckTime )update a set OffDuty1=(select top 1 checktime from OriginalData where EmployeeID=a.EmployeeID and CheckTime>=a.CheckDate and CheckTime<dateadd(day,1,a.CheckDate)) from OnOffDutyData adelete a from OriginalData a where not exists ( select 1 from OriginalData where EmployeeID=a.EmployeeID and convert(Nchar(10),CheckTime,120)=convert(Nchar(10),a.CheckTime,120) and CheckTime<a.CheckTime )update a set OnDuty2=(select top 1 checktime from OriginalData where EmployeeID=a.EmployeeID and CheckTime>=a.CheckDate and CheckTime<dateadd(day,1,a.CheckDate)) from OnOffDutyData adelete a from OriginalData a where not exists ( select 1 from OriginalData where EmployeeID=a.EmployeeID and convert(Nchar(10),CheckTime,120)=convert(Nchar(10),a.CheckTime,120) and CheckTime<a.CheckTime )update a set OffDuty2=(select top 1 checktime from OriginalData where EmployeeID=a.EmployeeID and CheckTime>=a.CheckDate and CheckTime<dateadd(day,1,a.CheckDate)) from OnOffDutyData adelete a from OriginalData a where not exists ( select 1 from OriginalData where EmployeeID=a.EmployeeID and convert(Nchar(10),CheckTime,120)=convert(Nchar(10),a.CheckTime,120) and CheckTime<a.CheckTime )update a set OnDuty3=(select top 1 checktime from OriginalData where EmployeeID=a.EmployeeID and CheckTime>=a.CheckDate and CheckTime<dateadd(day,1,a.CheckDate)) from OnOffDutyData adelete a from OriginalData a where not exists ( select 1 from OriginalData where EmployeeID=a.EmployeeID and convert(Nchar(10),CheckTime,120)=convert(Nchar(10),a.CheckTime,120) and CheckTime<a.CheckTime )update a set OffDuty3=(select top 1 checktime from OriginalData where EmployeeID=a.EmployeeID and CheckTime>=a.CheckDate and CheckTime<dateadd(day,1,a.CheckDate)) from OnOffDutyData adelete a from OriginalData a where not exists ( select 1 from OriginalData where EmployeeID=a.EmployeeID and convert(Nchar(10),CheckTime,120)=convert(Nchar(10),a.CheckTime,120) and CheckTime<a.CheckTime )
--打卡记录表 CREATE TABLE OriginalData([id] int IDENTITY(1,1),EmployeeID int,CheckTime datetime) INSERT INTO OriginalData SELECT 1,'2007-06-11 08:01' UNION ALL SELECT 1,'2007-06-11 12:02' UNION ALL SELECT 1,'2007-06-11 13:05' UNION ALL SELECT 1,'2007-06-11 17:40' UNION ALL SELECT 1,'2007-06-11 19:00' UNION ALL SELECT 1,'2007-06-11 23:42' UNION ALL SELECT 1,'2007-06-11 23:58' UNION ALL SELECT 1,'2007-06-12 07:50' UNION ALL SELECT 1,'2007-06-12 12:00' UNION ALL SELECT 3,'2007-06-11 20:00' UNION ALL SELECT 3,'2007-06-12 04:00' UNION ALL SELECT 3,'2007-06-12 07:55' UNION ALL SELECT 3,'2007-06-12 12:00' UNION ALL SELECT 3,'2007-06-12 13:00' UNION ALL SELECT 3,'2007-06-12 17:35' --考勤表 CREATE TABLE OnOffDutyData(EmployeeID int,CheckDate datetime ,OnDuty1 datetime,OffDuty1 datetime ,OnDuty2 datetime,OffDuty2 datetime ,OnDuty3 datetime,OffDuty3 datetime ,OnDuty4 datetime,OffDuty4 datetime) INSERT INTO OnOffDutyData (EmployeeID,CheckDate) SELECT 1,'2007-06-11' UNION ALL SELECT 1,'2007-06-12' UNION ALL SELECT 3,'2007-06-11' UNION ALL SELECT 3,'2007-06-12' declare @t table(EmployeeID int,CheckDate datetime,OnDuty1 varchar(10),OnDuty2 varchar(10),OnDuty3 varchar(10),OnDuty4 varchar(10),OnDuty5 varchar(10),OnDuty6 varchar(10),OnDuty7 varchar(10),OnDuty8 varchar(10)) declare @lsb table(EmployeeID int,d datetime,m varchar(10),cnt int)insert @lsb SELECT b.EmployeeID,d=convert(char(10),b.CheckTime,21),m=right(convert(char(16),b.CheckTime,21),5), Cnt=(select count(1) from OriginalData where EmployeeID=b.EmployeeID and convert(char(10),b.CheckTime,21)=convert(char(10),CheckTime,21) and CheckTime<b.CheckTime ) FROM OriginalData binsert @t SELECT a.EmployeeID,CheckDate=convert(char(10),a.CheckDate,21), OnDuty1=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 0 then m else null end), OnDuty1=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 1 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)), OnDuty2=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 2 then m else null end), OnDuty2=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 3 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)), OnDuty3=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 4 then m else null end), OnDuty3=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 5 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)), OnDuty4=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 6 then m else null end), OnDuty4=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 7 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)) FROM OnOffDutyData a left join @lsb b on a.EmployeeID=b.EmployeeID group by a.EmployeeID,CheckDate order by a.EmployeeID,CheckDateselect EmployeeID,CheckDate, OnDuty1,OnDuty2=case when OnDuty1 is not null then OnDuty2 else null end, OnDuty3,OnDuty4=case when OnDuty3 is not null then OnDuty4 else null end, OnDuty5,OnDuty6=case when OnDuty5 is not null then OnDuty6 else null end, OnDuty7,OnDuty8=case when OnDuty7 is not null then OnDuty8 else null end from @t
--打卡记录表 CREATE TABLE OriginalData([id] int IDENTITY(1,1),EmployeeID int,CheckTime datetime) INSERT INTO OriginalData SELECT 1,'2007-06-11 08:01' UNION ALL SELECT 1,'2007-06-11 12:02' UNION ALL SELECT 1,'2007-06-11 13:05' UNION ALL SELECT 1,'2007-06-11 17:40' UNION ALL SELECT 1,'2007-06-11 19:00' UNION ALL SELECT 1,'2007-06-11 23:42' UNION ALL SELECT 1,'2007-06-11 23:58' UNION ALL SELECT 1,'2007-06-12 07:50' UNION ALL SELECT 1,'2007-06-12 12:00' UNION ALL SELECT 3,'2007-06-11 20:00' UNION ALL SELECT 3,'2007-06-12 04:00' UNION ALL SELECT 3,'2007-06-12 07:55' UNION ALL SELECT 3,'2007-06-12 12:00' UNION ALL SELECT 3,'2007-06-12 13:00' UNION ALL SELECT 3,'2007-06-12 17:35' --考勤表 CREATE TABLE OnOffDutyData(EmployeeID int,CheckDate datetime ,OnDuty1 datetime,OffDuty1 datetime ,OnDuty2 datetime,OffDuty2 datetime ,OnDuty3 datetime,OffDuty3 datetime ,OnDuty4 datetime,OffDuty4 datetime) INSERT INTO OnOffDutyData (EmployeeID,CheckDate) SELECT 1,'2007-06-11' UNION ALL SELECT 1,'2007-06-12' UNION ALL SELECT 3,'2007-06-11' UNION ALL SELECT 3,'2007-06-12' declare @t table(EmployeeID int,CheckDate datetime,OnDuty1 varchar(10),OnDuty2 varchar(10),OnDuty3 varchar(10),OnDuty4 varchar(10),OnDuty5 varchar(10),OnDuty6 varchar(10),OnDuty7 varchar(10),OnDuty8 varchar(10)) declare @lsb table(EmployeeID int,d datetime,m varchar(10),cnt int)insert @lsb SELECT b.EmployeeID,d=convert(char(10),b.CheckTime,21),m=right(convert(char(16),b.CheckTime,21),5), Cnt=(select count(1) from OriginalData where EmployeeID=b.EmployeeID and convert(char(10),b.CheckTime,21)=convert(char(10),CheckTime,21) and CheckTime<b.CheckTime ) FROM OriginalData binsert @t SELECT a.EmployeeID,CheckDate=convert(char(10),a.CheckDate,21), OnDuty1=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 0 then m else null end), OnDuty1=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 1 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)), OnDuty2=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 2 then m else null end), OnDuty2=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 3 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)), OnDuty3=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 4 then m else null end), OnDuty3=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 5 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)), OnDuty4=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 6 then m else null end), OnDuty4=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 7 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)) FROM OnOffDutyData a left join @lsb b on a.EmployeeID=b.EmployeeID group by a.EmployeeID,CheckDate order by a.EmployeeID,CheckDatedelete from OnOffDutyDatainsert OnOffDutyData select EmployeeID,CheckDate, CheckDate+OnDuty1,OnDuty2=case when OnDuty1 is not null then CheckDate+OnDuty2 else null end, CheckDate+OnDuty3,OnDuty4=case when OnDuty3 is not null then CheckDate+OnDuty4 else null end, CheckDate+OnDuty5,OnDuty6=case when OnDuty5 is not null then CheckDate+OnDuty6 else null end, CheckDate+OnDuty7,OnDuty8=case when OnDuty7 is not null then CheckDate+OnDuty8 else null end from @tselect * from OnOffDutyData
to: leo_lesley(leo) ( ) 方法不错。我先测试,看看。希望还有更好的方法。再加100分
------------看看这个用的是两个表变量,然后直接update处理的,不用先删除,再插入。 --打卡记录表 CREATE TABLE OriginalData([id] int IDENTITY(1,1),EmployeeID int,CheckTime datetime) INSERT INTO OriginalData SELECT 1,'2007-06-11 08:01' UNION ALL SELECT 1,'2007-06-11 12:02' UNION ALL SELECT 1,'2007-06-11 13:05' UNION ALL SELECT 1,'2007-06-11 17:40' UNION ALL SELECT 1,'2007-06-11 19:00' UNION ALL SELECT 1,'2007-06-11 23:42' UNION ALL SELECT 1,'2007-06-11 23:58' UNION ALL SELECT 1,'2007-06-12 07:50' UNION ALL SELECT 1,'2007-06-12 12:00' UNION ALL SELECT 3,'2007-06-11 20:00' UNION ALL SELECT 3,'2007-06-12 04:00' UNION ALL SELECT 3,'2007-06-12 07:55' UNION ALL SELECT 3,'2007-06-12 12:00' UNION ALL SELECT 3,'2007-06-12 13:00' UNION ALL SELECT 3,'2007-06-12 17:35' go --考勤表 CREATE TABLE OnOffDutyData(EmployeeID int,CheckDate datetime ,OnDuty1 datetime,OffDuty1 datetime ,OnDuty2 datetime,OffDuty2 datetime ,OnDuty3 datetime,OffDuty3 datetime ,OnDuty4 datetime,OffDuty4 datetime) INSERT INTO OnOffDutyData (EmployeeID,CheckDate) SELECT 1,'2007-06-11' UNION ALL SELECT 1,'2007-06-12' UNION ALL SELECT 3,'2007-06-11' UNION ALL SELECT 3,'2007-06-12' go declare @t table(EmployeeID int,CheckDate datetime,OnDuty1 varchar(10),OnDuty2 varchar(10),OnDuty3 varchar(10),OnDuty4 varchar(10),OnDuty5 varchar(10),OnDuty6 varchar(10),OnDuty7 varchar(10),OnDuty8 varchar(10)) declare @lsb table(EmployeeID int,d datetime,m varchar(10),cnt int)insert @lsb SELECT b.EmployeeID,d=convert(char(10),b.CheckTime,21),m=right(convert(char(16),b.CheckTime,21),5), Cnt=(select count(1) from OriginalData where EmployeeID=b.EmployeeID and convert(char(10),b.CheckTime,21)=convert(char(10),CheckTime,21) and CheckTime<b.CheckTime ) FROM OriginalData binsert @t SELECT a.EmployeeID,CheckDate=convert(char(10),a.CheckDate,21), OnDuty1=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 0 then m else null end), OnDuty1=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 1 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)), OnDuty2=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 2 then m else null end), OnDuty2=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 3 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)), OnDuty3=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 4 then m else null end), OnDuty3=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 5 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)), OnDuty4=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 6 then m else null end), OnDuty4=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 7 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)) FROM OnOffDutyData a left join @lsb b on a.EmployeeID=b.EmployeeID group by a.EmployeeID,CheckDate order by a.EmployeeID,CheckDate update a set a.OnDuty1=t.CheckDate+t.OnDuty1, a.OffDuty1=case when t.OnDuty1 is not null then t.CheckDate+t.OnDuty2 else null end, a.OnDuty2=t.CheckDate+t.OnDuty3, a.OffDuty2=case when t.OnDuty3 is not null then t.CheckDate+t.OnDuty4 else null end, a.OnDuty3=t.CheckDate+t.OnDuty5, a.OffDuty3=case when t.OnDuty5 is not null then t.CheckDate+t.OnDuty6 else null end, a.OnDuty4=t.CheckDate+t.OnDuty7, a.OffDuty4=case when t.OnDuty7 is not null then t.CheckDate+t.OnDuty8 else null end from OnOffDutyData a,@t t where a.EmployeeID=t.EmployeeID and a.CheckDate=t.CheckDateselect * from OnOffDutyData drop table OnOffDutyData,OriginalData
非常感谢leo_lesley(leo)的帮助,方法不错,但还有一点小问题,已经标出问题点。 我明天再看一下,怎么样改进。-------------------------------------------------------------打卡记录表 CREATE TABLE OriginalData([id] int IDENTITY(1,1),EmployeeID int,CheckTime datetime) INSERT INTO OriginalData SELECT 1,'2007-06-11 08:01' UNION ALL SELECT 1,'2007-06-11 12:02' UNION ALL SELECT 1,'2007-06-11 13:05' UNION ALL SELECT 1,'2007-06-11 17:40' UNION ALL SELECT 1,'2007-06-11 19:00' UNION ALL --SELECT 1,'2007-06-11 23:42' UNION ALL --没有这句子,结果的第一行记录就有问题,无法记录第2天的第1次刷卡记录 SELECT 1,'2007-06-11 23:58' UNION ALL SELECT 1,'2007-06-12 07:50' UNION ALL SELECT 1,'2007-06-12 12:00' UNION ALL SELECT 3,'2007-06-11 20:00' UNION ALL SELECT 3,'2007-06-12 04:00' UNION ALL SELECT 3,'2007-06-12 07:55' UNION ALL SELECT 3,'2007-06-12 12:00' UNION ALL SELECT 3,'2007-06-12 13:00' UNION ALL SELECT 3,'2007-06-12 17:35' go --考勤表 CREATE TABLE OnOffDutyData(EmployeeID int,CheckDate datetime ,OnDuty1 datetime,OffDuty1 datetime ,OnDuty2 datetime,OffDuty2 datetime ,OnDuty3 datetime,OffDuty3 datetime ,OnDuty4 datetime,OffDuty4 datetime) INSERT INTO OnOffDutyData (EmployeeID,CheckDate) SELECT 1,'2007-06-11' UNION ALL SELECT 1,'2007-06-12' UNION ALL SELECT 3,'2007-06-11' UNION ALL SELECT 3,'2007-06-12' go declare @t table(EmployeeID int,CheckDate datetime,OnDuty1 varchar(10),OnDuty2 varchar(10),OnDuty3 varchar(10),OnDuty4 varchar(10),OnDuty5 varchar(10),OnDuty6 varchar(10),OnDuty7 varchar(10),OnDuty8 varchar(10)) declare @lsb table(EmployeeID int,d datetime,m varchar(10),cnt int)insert @lsb SELECT b.EmployeeID,d=convert(char(10),b.CheckTime,21),m=right(convert(char(16),b.CheckTime,21),5), Cnt=(select count(1) from OriginalData where EmployeeID=b.EmployeeID and convert(char(10),b.CheckTime,21)=convert(char(10),CheckTime,21) and CheckTime<b.CheckTime ) FROM OriginalData binsert @t SELECT a.EmployeeID,CheckDate=convert(char(10),a.CheckDate,21), OnDuty1=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 0 then m else null end), OnDuty1=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 1 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)), OnDuty2=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 2 then m else null end), OnDuty2=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 3 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)), OnDuty3=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 4 then m else null end), OnDuty3=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 5 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)), OnDuty4=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 6 then m else null end), OnDuty4=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 7 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)) FROM OnOffDutyData a left join @lsb b on a.EmployeeID=b.EmployeeIDgroup by a.EmployeeID,CheckDate order by a.EmployeeID,CheckDateSELECT * FROM @t update a set a.OnDuty1=t.CheckDate+t.OnDuty1, a.OffDuty1=case when t.OnDuty1 is not null then t.CheckDate+t.OnDuty2 else null end, a.OnDuty2=t.CheckDate+t.OnDuty3, a.OffDuty2=case when t.OnDuty3 is not null then t.CheckDate+t.OnDuty4 else null end, a.OnDuty3=t.CheckDate+t.OnDuty5, a.OffDuty3=case when t.OnDuty5 is not null then t.CheckDate+t.OnDuty6 else null end, a.OnDuty4=t.CheckDate+t.OnDuty7, a.OffDuty4=case when t.OnDuty7 is not null then t.CheckDate+t.OnDuty8 else null end from OnOffDutyData a,@t t where a.EmployeeID=t.EmployeeID and a.CheckDate=t.CheckDateselect * from OnOffDutyData drop table OnOffDutyData,OriginalData
--总体思想,先对时间进行排序,再就结果存到temp table中--打卡记录表 CREATE TABLE OriginalData([id] int IDENTITY(1,1),EmployeeID int,CheckTime datetime) INSERT INTO OriginalData SELECT 1,'2007-06-11 08:01' UNION ALL SELECT 1,'2007-06-11 12:02' UNION ALL SELECT 1,'2007-06-11 13:05' UNION ALL SELECT 1,'2007-06-11 17:40' UNION ALL SELECT 1,'2007-06-11 19:00' UNION ALL SELECT 1,'2007-06-11 23:42' UNION ALL SELECT 1,'2007-06-11 23:58' UNION ALL SELECT 1,'2007-06-12 07:50' UNION ALL SELECT 1,'2007-06-12 12:00' UNION ALL SELECT 3,'2007-06-11 20:00' UNION ALL SELECT 3,'2007-06-12 04:00' UNION ALL SELECT 3,'2007-06-12 07:55' UNION ALL SELECT 3,'2007-06-12 12:00' UNION ALL SELECT 3,'2007-06-12 13:00' UNION ALL SELECT 3,'2007-06-12 17:35' --考勤表 CREATE TABLE OnOffDutyData(EmployeeID int,CheckDate datetime ,OnDuty1 varchar(10),OffDuty1 varchar(10) ,OnDuty2 varchar(10),OffDuty2 varchar(10) ,OnDuty3 varchar(10),OffDuty3 varchar(10) ,OnDuty4 varchar(10),OffDuty4 varchar(10)) INSERT INTO OnOffDutyData (EmployeeID,CheckDate) SELECT 1,'2007-06-11' UNION ALL SELECT 1,'2007-06-12' UNION ALL SELECT 3,'2007-06-11' UNION ALL SELECT 3,'2007-06-12' --SELECT * ,left(right(convert(varchar(23),checkTime,120),8),5) FROM OriginalData --SELECT * FROM OnOffDutyData -- update result update OnOffDutyData set onDuty1=(select top 1 left(right(convert(varchar(23),checkTime,120),8),5) FROM OriginalData b where EmployeeID=b.EmployeeID and datediff(dd,checkTime,b.checkTime)=0 order by checkTime )-- 先对时间进行排序,存到一个temp表中,提高查询速度 select * ,layer=(select count(1) from OriginalData where EmployeeID=b.EmployeeID and datediff(dd,checkTime,b.checkTime)=0 and checkTime<=b.checkTime) into #temp from OriginalData b----最终结果 select EmployeeID,CheckDate, OnDuty1=isnull((select left(right(convert(varchar(23),checkTime,120),8),5) from #temp where EmployeeID=b.EmployeeID and datediff(dd,checkTime,b.checkDate)=0 and layer=1),null), offDuty1=isnull((select left(right(convert(varchar(23),checkTime,120),8),5) from #temp where EmployeeID=b.EmployeeID and datediff(dd,checkTime,b.checkDate)=0 and layer=2),null), OnDuty2=isnull((select left(right(convert(varchar(23),checkTime,120),8),5) from #temp where EmployeeID=b.EmployeeID and datediff(dd,checkTime,b.checkDate)=0 and layer=3),null), offDuty2=isnull((select left(right(convert(varchar(23),checkTime,120),8),5) from #temp where EmployeeID=b.EmployeeID and datediff(dd,checkTime,b.checkDate)=0 and layer=4),null), OnDuty3=isnull((select left(right(convert(varchar(23),checkTime,120),8),5) from #temp where EmployeeID=b.EmployeeID and datediff(dd,checkTime,b.checkDate)=0 and layer=5),null), offDuty3=isnull((select left(right(convert(varchar(23),checkTime,120),8),5) from #temp where EmployeeID=b.EmployeeID and datediff(dd,checkTime,b.checkDate)=-1 and layer=1),null) from OnOffDutyData b--drop table drop table #temp drop table OnOffDutyData drop table OriginalData
SELECT EmployeeID,CheckTime, OnDuty1=max(OnDuty1), OnOffDuty1=ISNULL(max(OnOffDuty1),max(OnDuty4)), OnDuty2=case when max(OnOffDuty1) is null then NULL else ISNULL(max(OnDuty2),max(OnDuty4)) end, OnOffDuty2=case when max(OnDuty2) is null then NULL else ISNULL(max(OnOffDuty2),max(OnDuty4)) end, OnDuty3=case when max(OnOffDuty2) is null then NULL else ISNULL(max(OnDuty3),max(OnDuty4)) end, OnOffDuty3=case when max(OnDuty3) is null then NULL else ISNULL(max(OnOffDuty3),max(OnDuty4)) end, OnDuty4=case when max(OnOffDuty3) is null then NULL else max(OnDuty4) end FROM
(select EmployeeID,CheckTime=convert(varchar(10),CheckTime,120), OnDuty1=(select top 1 convert(varchar(5),CheckTime,108) from @OriginalData where EmployeeID = t.EmployeeID and datediff(dd,CheckTime,t.CheckTime) = 0 order by CheckTime), OnOffDuty1=(select convert(varchar(5),CheckTime,108) from @OriginalData as a where EmployeeID = t.EmployeeID and datediff(dd,CheckTime,t.CheckTime) = 0 and (select count(*) from @OriginalData where EmployeeID = a.EmployeeID and datediff(dd,CheckTime,a.CheckTime) = 0 and CheckTime <= a.CheckTime)= 2), OnDuty2=(select convert(varchar(5),CheckTime,108) from @OriginalData as a where EmployeeID = t.EmployeeID and datediff(dd,CheckTime,t.CheckTime) = 0 and (select count(*) from @OriginalData where EmployeeID = a.EmployeeID and datediff(dd,CheckTime,a.CheckTime) = 0 and CheckTime <= a.CheckTime)= 3),
OnOffDuty2=(select convert(varchar(5),CheckTime,108) from @OriginalData as a where EmployeeID = t.EmployeeID and datediff(dd,CheckTime,t.CheckTime) = 0 and (select count(*) from @OriginalData where EmployeeID = a.EmployeeID and datediff(dd,CheckTime,a.CheckTime) = 0 and CheckTime <= a.CheckTime)= 4), OnDuty3=(select convert(varchar(5),CheckTime,108) from @OriginalData as a where EmployeeID = t.EmployeeID and datediff(dd,CheckTime,t.CheckTime) = 0 and (select count(*) from @OriginalData where EmployeeID = a.EmployeeID and datediff(dd,CheckTime,a.CheckTime) = 0 and CheckTime <= a.CheckTime)= 5), OnOffDuty3=(select convert(varchar(5),CheckTime,108) from @OriginalData as a where EmployeeID = t.EmployeeID and datediff(dd,CheckTime,t.CheckTime) = 0 and (select count(*) from @OriginalData where EmployeeID = a.EmployeeID and datediff(dd,CheckTime,a.CheckTime) = 0 and CheckTime <= a.CheckTime)= 6),
OnDuty4=(select top 1 convert(varchar(5),CheckTime,108) from @OriginalData as a where EmployeeID = t.EmployeeID and datediff(dd,t.CheckTime,CheckTime)=1 order by CheckTime) from @OriginalData as t ) AS x GROUP BY EmployeeID,CheckTime ORDER BY 1,2 --请楼主把上面三段SQL连起来.我这里无法把完整的帖出来(无法发送),只好拆开,不知道CSDN又怎么了.
INSERT INTO 不是重要,主要是处理打卡数据,怎么样提高运行效率。
找不到一个好的方法。
set OnDuty1=(select top 1 checktime from OriginalData where EmployeeID=a.EmployeeID and CheckTime>=a.CheckDate and CheckTime<dateadd(day,1,a.CheckDate)),
OnDuty4=(select top 1 checktime from OriginalData where EmployeeID=a.EmployeeID and CheckTime>=dateadd(day,1,a.CheckDate) and CheckTime<dateadd(day,2,a.CheckDate))
from OnOffDutyData adelete a
from OriginalData a
where not exists (
select 1 from OriginalData
where EmployeeID=a.EmployeeID and
convert(Nchar(10),CheckTime,120)=convert(Nchar(10),a.CheckTime,120)
and CheckTime<a.CheckTime
)update a
set OffDuty1=(select top 1 checktime from OriginalData where EmployeeID=a.EmployeeID and CheckTime>=a.CheckDate and CheckTime<dateadd(day,1,a.CheckDate))
from OnOffDutyData adelete a
from OriginalData a
where not exists (
select 1 from OriginalData
where EmployeeID=a.EmployeeID and
convert(Nchar(10),CheckTime,120)=convert(Nchar(10),a.CheckTime,120)
and CheckTime<a.CheckTime
)update a
set OnDuty2=(select top 1 checktime from OriginalData where EmployeeID=a.EmployeeID and CheckTime>=a.CheckDate and CheckTime<dateadd(day,1,a.CheckDate))
from OnOffDutyData adelete a
from OriginalData a
where not exists (
select 1 from OriginalData
where EmployeeID=a.EmployeeID and
convert(Nchar(10),CheckTime,120)=convert(Nchar(10),a.CheckTime,120)
and CheckTime<a.CheckTime
)update a
set OffDuty2=(select top 1 checktime from OriginalData where EmployeeID=a.EmployeeID and CheckTime>=a.CheckDate and CheckTime<dateadd(day,1,a.CheckDate))
from OnOffDutyData adelete a
from OriginalData a
where not exists (
select 1 from OriginalData
where EmployeeID=a.EmployeeID and
convert(Nchar(10),CheckTime,120)=convert(Nchar(10),a.CheckTime,120)
and CheckTime<a.CheckTime
)update a
set OnDuty3=(select top 1 checktime from OriginalData where EmployeeID=a.EmployeeID and CheckTime>=a.CheckDate and CheckTime<dateadd(day,1,a.CheckDate))
from OnOffDutyData adelete a
from OriginalData a
where not exists (
select 1 from OriginalData
where EmployeeID=a.EmployeeID and
convert(Nchar(10),CheckTime,120)=convert(Nchar(10),a.CheckTime,120)
and CheckTime<a.CheckTime
)update a
set OffDuty3=(select top 1 checktime from OriginalData where EmployeeID=a.EmployeeID and CheckTime>=a.CheckDate and CheckTime<dateadd(day,1,a.CheckDate))
from OnOffDutyData adelete a
from OriginalData a
where not exists (
select 1 from OriginalData
where EmployeeID=a.EmployeeID and
convert(Nchar(10),CheckTime,120)=convert(Nchar(10),a.CheckTime,120)
and CheckTime<a.CheckTime
)
CREATE TABLE OriginalData([id] int IDENTITY(1,1),EmployeeID int,CheckTime datetime)
INSERT INTO OriginalData
SELECT 1,'2007-06-11 08:01' UNION ALL
SELECT 1,'2007-06-11 12:02' UNION ALL
SELECT 1,'2007-06-11 13:05' UNION ALL
SELECT 1,'2007-06-11 17:40' UNION ALL
SELECT 1,'2007-06-11 19:00' UNION ALL
SELECT 1,'2007-06-11 23:42' UNION ALL
SELECT 1,'2007-06-11 23:58' UNION ALL
SELECT 1,'2007-06-12 07:50' UNION ALL
SELECT 1,'2007-06-12 12:00' UNION ALL
SELECT 3,'2007-06-11 20:00' UNION ALL
SELECT 3,'2007-06-12 04:00' UNION ALL
SELECT 3,'2007-06-12 07:55' UNION ALL
SELECT 3,'2007-06-12 12:00' UNION ALL
SELECT 3,'2007-06-12 13:00' UNION ALL
SELECT 3,'2007-06-12 17:35'
--考勤表
CREATE TABLE OnOffDutyData(EmployeeID int,CheckDate datetime
,OnDuty1 datetime,OffDuty1 datetime
,OnDuty2 datetime,OffDuty2 datetime
,OnDuty3 datetime,OffDuty3 datetime
,OnDuty4 datetime,OffDuty4 datetime)
INSERT INTO OnOffDutyData (EmployeeID,CheckDate)
SELECT 1,'2007-06-11' UNION ALL
SELECT 1,'2007-06-12' UNION ALL
SELECT 3,'2007-06-11' UNION ALL
SELECT 3,'2007-06-12' declare @t table(EmployeeID int,CheckDate datetime,OnDuty1 varchar(10),OnDuty2 varchar(10),OnDuty3 varchar(10),OnDuty4 varchar(10),OnDuty5 varchar(10),OnDuty6 varchar(10),OnDuty7 varchar(10),OnDuty8 varchar(10))
declare @lsb table(EmployeeID int,d datetime,m varchar(10),cnt int)insert @lsb
SELECT b.EmployeeID,d=convert(char(10),b.CheckTime,21),m=right(convert(char(16),b.CheckTime,21),5),
Cnt=(select count(1) from OriginalData where EmployeeID=b.EmployeeID and convert(char(10),b.CheckTime,21)=convert(char(10),CheckTime,21) and CheckTime<b.CheckTime )
FROM OriginalData binsert @t
SELECT a.EmployeeID,CheckDate=convert(char(10),a.CheckDate,21),
OnDuty1=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 0 then m else null end),
OnDuty1=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 1 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)),
OnDuty2=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 2 then m else null end),
OnDuty2=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 3 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)),
OnDuty3=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 4 then m else null end),
OnDuty3=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 5 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)),
OnDuty4=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 6 then m else null end),
OnDuty4=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 7 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end))
FROM OnOffDutyData a left join @lsb b on a.EmployeeID=b.EmployeeID
group by a.EmployeeID,CheckDate
order by a.EmployeeID,CheckDateselect EmployeeID,CheckDate,
OnDuty1,OnDuty2=case when OnDuty1 is not null then OnDuty2 else null end,
OnDuty3,OnDuty4=case when OnDuty3 is not null then OnDuty4 else null end,
OnDuty5,OnDuty6=case when OnDuty5 is not null then OnDuty6 else null end,
OnDuty7,OnDuty8=case when OnDuty7 is not null then OnDuty8 else null end
from @t
CREATE TABLE OriginalData([id] int IDENTITY(1,1),EmployeeID int,CheckTime datetime)
INSERT INTO OriginalData
SELECT 1,'2007-06-11 08:01' UNION ALL
SELECT 1,'2007-06-11 12:02' UNION ALL
SELECT 1,'2007-06-11 13:05' UNION ALL
SELECT 1,'2007-06-11 17:40' UNION ALL
SELECT 1,'2007-06-11 19:00' UNION ALL
SELECT 1,'2007-06-11 23:42' UNION ALL
SELECT 1,'2007-06-11 23:58' UNION ALL
SELECT 1,'2007-06-12 07:50' UNION ALL
SELECT 1,'2007-06-12 12:00' UNION ALL
SELECT 3,'2007-06-11 20:00' UNION ALL
SELECT 3,'2007-06-12 04:00' UNION ALL
SELECT 3,'2007-06-12 07:55' UNION ALL
SELECT 3,'2007-06-12 12:00' UNION ALL
SELECT 3,'2007-06-12 13:00' UNION ALL
SELECT 3,'2007-06-12 17:35'
--考勤表
CREATE TABLE OnOffDutyData(EmployeeID int,CheckDate datetime
,OnDuty1 datetime,OffDuty1 datetime
,OnDuty2 datetime,OffDuty2 datetime
,OnDuty3 datetime,OffDuty3 datetime
,OnDuty4 datetime,OffDuty4 datetime)
INSERT INTO OnOffDutyData (EmployeeID,CheckDate)
SELECT 1,'2007-06-11' UNION ALL
SELECT 1,'2007-06-12' UNION ALL
SELECT 3,'2007-06-11' UNION ALL
SELECT 3,'2007-06-12'
declare @t table(EmployeeID int,CheckDate datetime,OnDuty1 varchar(10),OnDuty2 varchar(10),OnDuty3 varchar(10),OnDuty4 varchar(10),OnDuty5 varchar(10),OnDuty6 varchar(10),OnDuty7 varchar(10),OnDuty8 varchar(10))
declare @lsb table(EmployeeID int,d datetime,m varchar(10),cnt int)insert @lsb
SELECT b.EmployeeID,d=convert(char(10),b.CheckTime,21),m=right(convert(char(16),b.CheckTime,21),5),
Cnt=(select count(1) from OriginalData where EmployeeID=b.EmployeeID and convert(char(10),b.CheckTime,21)=convert(char(10),CheckTime,21) and CheckTime<b.CheckTime )
FROM OriginalData binsert @t
SELECT a.EmployeeID,CheckDate=convert(char(10),a.CheckDate,21),
OnDuty1=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 0 then m else null end),
OnDuty1=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 1 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)),
OnDuty2=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 2 then m else null end),
OnDuty2=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 3 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)),
OnDuty3=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 4 then m else null end),
OnDuty3=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 5 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)),
OnDuty4=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 6 then m else null end),
OnDuty4=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 7 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end))
FROM OnOffDutyData a left join @lsb b on a.EmployeeID=b.EmployeeID
group by a.EmployeeID,CheckDate
order by a.EmployeeID,CheckDatedelete from OnOffDutyDatainsert OnOffDutyData
select EmployeeID,CheckDate,
CheckDate+OnDuty1,OnDuty2=case when OnDuty1 is not null then CheckDate+OnDuty2 else null end,
CheckDate+OnDuty3,OnDuty4=case when OnDuty3 is not null then CheckDate+OnDuty4 else null end,
CheckDate+OnDuty5,OnDuty6=case when OnDuty5 is not null then CheckDate+OnDuty6 else null end,
CheckDate+OnDuty7,OnDuty8=case when OnDuty7 is not null then CheckDate+OnDuty8 else null end
from @tselect * from OnOffDutyData
leo_lesley(leo) ( ) 方法不错。我先测试,看看。希望还有更好的方法。再加100分
--打卡记录表
CREATE TABLE OriginalData([id] int IDENTITY(1,1),EmployeeID int,CheckTime datetime)
INSERT INTO OriginalData
SELECT 1,'2007-06-11 08:01' UNION ALL
SELECT 1,'2007-06-11 12:02' UNION ALL
SELECT 1,'2007-06-11 13:05' UNION ALL
SELECT 1,'2007-06-11 17:40' UNION ALL
SELECT 1,'2007-06-11 19:00' UNION ALL
SELECT 1,'2007-06-11 23:42' UNION ALL
SELECT 1,'2007-06-11 23:58' UNION ALL
SELECT 1,'2007-06-12 07:50' UNION ALL
SELECT 1,'2007-06-12 12:00' UNION ALL
SELECT 3,'2007-06-11 20:00' UNION ALL
SELECT 3,'2007-06-12 04:00' UNION ALL
SELECT 3,'2007-06-12 07:55' UNION ALL
SELECT 3,'2007-06-12 12:00' UNION ALL
SELECT 3,'2007-06-12 13:00' UNION ALL
SELECT 3,'2007-06-12 17:35' go --考勤表
CREATE TABLE OnOffDutyData(EmployeeID int,CheckDate datetime
,OnDuty1 datetime,OffDuty1 datetime
,OnDuty2 datetime,OffDuty2 datetime
,OnDuty3 datetime,OffDuty3 datetime
,OnDuty4 datetime,OffDuty4 datetime)
INSERT INTO OnOffDutyData (EmployeeID,CheckDate)
SELECT 1,'2007-06-11' UNION ALL
SELECT 1,'2007-06-12' UNION ALL
SELECT 3,'2007-06-11' UNION ALL
SELECT 3,'2007-06-12' go declare @t table(EmployeeID int,CheckDate datetime,OnDuty1 varchar(10),OnDuty2 varchar(10),OnDuty3 varchar(10),OnDuty4 varchar(10),OnDuty5 varchar(10),OnDuty6 varchar(10),OnDuty7 varchar(10),OnDuty8 varchar(10))
declare @lsb table(EmployeeID int,d datetime,m varchar(10),cnt int)insert @lsb
SELECT b.EmployeeID,d=convert(char(10),b.CheckTime,21),m=right(convert(char(16),b.CheckTime,21),5),
Cnt=(select count(1) from OriginalData where EmployeeID=b.EmployeeID and convert(char(10),b.CheckTime,21)=convert(char(10),CheckTime,21) and CheckTime<b.CheckTime )
FROM OriginalData binsert @t
SELECT a.EmployeeID,CheckDate=convert(char(10),a.CheckDate,21),
OnDuty1=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 0 then m else null end),
OnDuty1=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 1 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)),
OnDuty2=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 2 then m else null end),
OnDuty2=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 3 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)),
OnDuty3=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 4 then m else null end),
OnDuty3=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 5 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)),
OnDuty4=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 6 then m else null end),
OnDuty4=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 7 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end))
FROM OnOffDutyData a left join @lsb b on a.EmployeeID=b.EmployeeID
group by a.EmployeeID,CheckDate
order by a.EmployeeID,CheckDate
update a
set a.OnDuty1=t.CheckDate+t.OnDuty1,
a.OffDuty1=case when t.OnDuty1 is not null then t.CheckDate+t.OnDuty2 else null end,
a.OnDuty2=t.CheckDate+t.OnDuty3,
a.OffDuty2=case when t.OnDuty3 is not null then t.CheckDate+t.OnDuty4 else null end,
a.OnDuty3=t.CheckDate+t.OnDuty5,
a.OffDuty3=case when t.OnDuty5 is not null then t.CheckDate+t.OnDuty6 else null end,
a.OnDuty4=t.CheckDate+t.OnDuty7,
a.OffDuty4=case when t.OnDuty7 is not null then t.CheckDate+t.OnDuty8 else null end
from OnOffDutyData a,@t t
where a.EmployeeID=t.EmployeeID and a.CheckDate=t.CheckDateselect * from OnOffDutyData
drop table OnOffDutyData,OriginalData
我明天再看一下,怎么样改进。-------------------------------------------------------------打卡记录表
CREATE TABLE OriginalData([id] int IDENTITY(1,1),EmployeeID int,CheckTime datetime)
INSERT INTO OriginalData
SELECT 1,'2007-06-11 08:01' UNION ALL
SELECT 1,'2007-06-11 12:02' UNION ALL
SELECT 1,'2007-06-11 13:05' UNION ALL
SELECT 1,'2007-06-11 17:40' UNION ALL
SELECT 1,'2007-06-11 19:00' UNION ALL
--SELECT 1,'2007-06-11 23:42' UNION ALL --没有这句子,结果的第一行记录就有问题,无法记录第2天的第1次刷卡记录
SELECT 1,'2007-06-11 23:58' UNION ALL
SELECT 1,'2007-06-12 07:50' UNION ALL
SELECT 1,'2007-06-12 12:00' UNION ALL
SELECT 3,'2007-06-11 20:00' UNION ALL
SELECT 3,'2007-06-12 04:00' UNION ALL
SELECT 3,'2007-06-12 07:55' UNION ALL
SELECT 3,'2007-06-12 12:00' UNION ALL
SELECT 3,'2007-06-12 13:00' UNION ALL
SELECT 3,'2007-06-12 17:35' go --考勤表
CREATE TABLE OnOffDutyData(EmployeeID int,CheckDate datetime
,OnDuty1 datetime,OffDuty1 datetime
,OnDuty2 datetime,OffDuty2 datetime
,OnDuty3 datetime,OffDuty3 datetime
,OnDuty4 datetime,OffDuty4 datetime)
INSERT INTO OnOffDutyData (EmployeeID,CheckDate)
SELECT 1,'2007-06-11' UNION ALL
SELECT 1,'2007-06-12' UNION ALL
SELECT 3,'2007-06-11' UNION ALL
SELECT 3,'2007-06-12' go declare @t table(EmployeeID int,CheckDate datetime,OnDuty1 varchar(10),OnDuty2 varchar(10),OnDuty3 varchar(10),OnDuty4 varchar(10),OnDuty5 varchar(10),OnDuty6 varchar(10),OnDuty7 varchar(10),OnDuty8 varchar(10))
declare @lsb table(EmployeeID int,d datetime,m varchar(10),cnt int)insert @lsb
SELECT b.EmployeeID,d=convert(char(10),b.CheckTime,21),m=right(convert(char(16),b.CheckTime,21),5),
Cnt=(select count(1) from OriginalData where EmployeeID=b.EmployeeID and convert(char(10),b.CheckTime,21)=convert(char(10),CheckTime,21) and CheckTime<b.CheckTime )
FROM OriginalData binsert @t
SELECT a.EmployeeID,CheckDate=convert(char(10),a.CheckDate,21),
OnDuty1=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 0 then m else null end),
OnDuty1=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 1 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)),
OnDuty2=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 2 then m else null end),
OnDuty2=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 3 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)),
OnDuty3=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 4 then m else null end),
OnDuty3=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 5 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end)),
OnDuty4=max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 6 then m else null end),
OnDuty4=isnull(max(case when a.EmployeeID=b.EmployeeID and convert(char(10),a.CheckDate,21)=d and cnt = 7 then m end),min(case when a.EmployeeID=b.EmployeeID and cnt = 0 and convert(char(10),a.CheckDate,21)<d then m end))
FROM OnOffDutyData a left join @lsb b on a.EmployeeID=b.EmployeeIDgroup by a.EmployeeID,CheckDate
order by a.EmployeeID,CheckDateSELECT * FROM @t
update a
set a.OnDuty1=t.CheckDate+t.OnDuty1,
a.OffDuty1=case when t.OnDuty1 is not null then t.CheckDate+t.OnDuty2 else null end,
a.OnDuty2=t.CheckDate+t.OnDuty3,
a.OffDuty2=case when t.OnDuty3 is not null then t.CheckDate+t.OnDuty4 else null end,
a.OnDuty3=t.CheckDate+t.OnDuty5,
a.OffDuty3=case when t.OnDuty5 is not null then t.CheckDate+t.OnDuty6 else null end,
a.OnDuty4=t.CheckDate+t.OnDuty7,
a.OffDuty4=case when t.OnDuty7 is not null then t.CheckDate+t.OnDuty8 else null end
from OnOffDutyData a,@t t
where a.EmployeeID=t.EmployeeID and a.CheckDate=t.CheckDateselect * from OnOffDutyData
drop table OnOffDutyData,OriginalData
CREATE TABLE OriginalData([id] int IDENTITY(1,1),EmployeeID int,CheckTime datetime)
INSERT INTO OriginalData
SELECT 1,'2007-06-11 08:01' UNION ALL
SELECT 1,'2007-06-11 12:02' UNION ALL
SELECT 1,'2007-06-11 13:05' UNION ALL
SELECT 1,'2007-06-11 17:40' UNION ALL
SELECT 1,'2007-06-11 19:00' UNION ALL
SELECT 1,'2007-06-11 23:42' UNION ALL
SELECT 1,'2007-06-11 23:58' UNION ALL
SELECT 1,'2007-06-12 07:50' UNION ALL
SELECT 1,'2007-06-12 12:00' UNION ALL
SELECT 3,'2007-06-11 20:00' UNION ALL
SELECT 3,'2007-06-12 04:00' UNION ALL
SELECT 3,'2007-06-12 07:55' UNION ALL
SELECT 3,'2007-06-12 12:00' UNION ALL
SELECT 3,'2007-06-12 13:00' UNION ALL
SELECT 3,'2007-06-12 17:35'
--考勤表
CREATE TABLE OnOffDutyData(EmployeeID int,CheckDate datetime
,OnDuty1 varchar(10),OffDuty1 varchar(10)
,OnDuty2 varchar(10),OffDuty2 varchar(10)
,OnDuty3 varchar(10),OffDuty3 varchar(10)
,OnDuty4 varchar(10),OffDuty4 varchar(10))
INSERT INTO OnOffDutyData (EmployeeID,CheckDate)
SELECT 1,'2007-06-11' UNION ALL
SELECT 1,'2007-06-12' UNION ALL
SELECT 3,'2007-06-11' UNION ALL
SELECT 3,'2007-06-12' --SELECT * ,left(right(convert(varchar(23),checkTime,120),8),5) FROM OriginalData
--SELECT * FROM OnOffDutyData
-- update result
update OnOffDutyData
set
onDuty1=(select top 1 left(right(convert(varchar(23),checkTime,120),8),5) FROM OriginalData b
where EmployeeID=b.EmployeeID and datediff(dd,checkTime,b.checkTime)=0 order by checkTime )-- 先对时间进行排序,存到一个temp表中,提高查询速度
select * ,layer=(select count(1) from OriginalData where EmployeeID=b.EmployeeID and datediff(dd,checkTime,b.checkTime)=0 and checkTime<=b.checkTime)
into #temp from OriginalData b----最终结果
select EmployeeID,CheckDate,
OnDuty1=isnull((select left(right(convert(varchar(23),checkTime,120),8),5) from #temp where EmployeeID=b.EmployeeID and datediff(dd,checkTime,b.checkDate)=0 and layer=1),null),
offDuty1=isnull((select left(right(convert(varchar(23),checkTime,120),8),5) from #temp where EmployeeID=b.EmployeeID and datediff(dd,checkTime,b.checkDate)=0 and layer=2),null),
OnDuty2=isnull((select left(right(convert(varchar(23),checkTime,120),8),5) from #temp where EmployeeID=b.EmployeeID and datediff(dd,checkTime,b.checkDate)=0 and layer=3),null),
offDuty2=isnull((select left(right(convert(varchar(23),checkTime,120),8),5) from #temp where EmployeeID=b.EmployeeID and datediff(dd,checkTime,b.checkDate)=0 and layer=4),null),
OnDuty3=isnull((select left(right(convert(varchar(23),checkTime,120),8),5) from #temp where EmployeeID=b.EmployeeID and datediff(dd,checkTime,b.checkDate)=0 and layer=5),null),
offDuty3=isnull((select left(right(convert(varchar(23),checkTime,120),8),5) from #temp where EmployeeID=b.EmployeeID and datediff(dd,checkTime,b.checkDate)=-1 and layer=1),null)
from OnOffDutyData b--drop table
drop table #temp
drop table OnOffDutyData
drop table OriginalData
OnDuty1=max(OnDuty1),
OnOffDuty1=ISNULL(max(OnOffDuty1),max(OnDuty4)),
OnDuty2=case when max(OnOffDuty1) is null then NULL else ISNULL(max(OnDuty2),max(OnDuty4)) end,
OnOffDuty2=case when max(OnDuty2) is null then NULL else ISNULL(max(OnOffDuty2),max(OnDuty4)) end,
OnDuty3=case when max(OnOffDuty2) is null then NULL else ISNULL(max(OnDuty3),max(OnDuty4)) end,
OnOffDuty3=case when max(OnDuty3) is null then NULL else ISNULL(max(OnOffDuty3),max(OnDuty4)) end,
OnDuty4=case when max(OnOffDuty3) is null then NULL else max(OnDuty4) end
FROM
OnDuty1=(select top 1 convert(varchar(5),CheckTime,108) from @OriginalData where EmployeeID = t.EmployeeID and datediff(dd,CheckTime,t.CheckTime) = 0 order by CheckTime),
OnOffDuty1=(select convert(varchar(5),CheckTime,108) from @OriginalData as a where EmployeeID = t.EmployeeID and datediff(dd,CheckTime,t.CheckTime) = 0 and
(select count(*) from @OriginalData where EmployeeID = a.EmployeeID and datediff(dd,CheckTime,a.CheckTime) = 0 and CheckTime <= a.CheckTime)= 2),
OnDuty2=(select convert(varchar(5),CheckTime,108) from @OriginalData as a where EmployeeID = t.EmployeeID and datediff(dd,CheckTime,t.CheckTime) = 0 and
(select count(*) from @OriginalData where EmployeeID = a.EmployeeID and datediff(dd,CheckTime,a.CheckTime) = 0 and CheckTime <= a.CheckTime)= 3),
(select count(*) from @OriginalData where EmployeeID = a.EmployeeID and datediff(dd,CheckTime,a.CheckTime) = 0 and CheckTime <= a.CheckTime)= 4),
OnDuty3=(select convert(varchar(5),CheckTime,108) from @OriginalData as a where EmployeeID = t.EmployeeID and datediff(dd,CheckTime,t.CheckTime) = 0 and
(select count(*) from @OriginalData where EmployeeID = a.EmployeeID and datediff(dd,CheckTime,a.CheckTime) = 0 and CheckTime <= a.CheckTime)= 5),
OnOffDuty3=(select convert(varchar(5),CheckTime,108) from @OriginalData as a where EmployeeID = t.EmployeeID and datediff(dd,CheckTime,t.CheckTime) = 0 and
(select count(*) from @OriginalData where EmployeeID = a.EmployeeID and datediff(dd,CheckTime,a.CheckTime) = 0 and CheckTime <= a.CheckTime)= 6),
from @OriginalData as t ) AS x
GROUP BY EmployeeID,CheckTime ORDER BY 1,2
--请楼主把上面三段SQL连起来.我这里无法把完整的帖出来(无法发送),只好拆开,不知道CSDN又怎么了.
EmployeeID CheckTime OnDuty1 OnOffDuty1 OnDuty2 OnOffDuty2 OnDuty3 OnOffDuty3 OnDuty4
----------- ---------- ------- ---------- ------- ---------- ------- ---------- -------
1 2007-06-11 08:01 12:02 13:05 17:40 19:00 23:42 07:50
1 2007-06-12 07:50 12:00 NULL NULL NULL NULL NULL
3 2007-06-11 20:00 04:00 NULL NULL NULL NULL NULL
3 2007-06-12 04:00 07:55 12:00 13:00 17:35 NULL NULL
2.修改考勤表,增加刷卡记录标记
3按标记依次更新update
以上意见仅供参考