T
tl_lyq
Unregistered / Unconfirmed
GUEST, unregistred user!
一个考勤处理的SQL过程,编完运行 速度太慢了,用了游标,请大家帮忙给修改一下啊.现在350人,一个月的考勤,处理居然要30分钟.代码请贴子查看. ( 积分: 40 )<br />CREATE PROCEDURE [dbo].[KqCalc] @sdate datetime,@edate datetime AS<br><br>set nocount on <br>declare @tmpdate0 datetime,@nmonths int<br><br>IF @edate<@sdate <br>begin<br> set @tmpdate0=@sdate set @sdate=@edate set @edate=@tmpdate0 <br>end<br> <br>set @nmonths=year(@edate+1)*12+MONTH(@edate+1)-YEAR(@sdate-1)*12-MONTH(@sdate-1)+1<br><br>declare <br> @tmpdate varchar(20), @tmpdate1 datetime,@currqpre varchar(10),@currq varchar(10) ,@currqnext varchar(20),@csjfwa1 varchar(20),@csjfwa2 varchar(20),@csjfwb1 varchar(20),@csjfwb2 varchar(20),@sjtmp varchar(20),<br> @ndays int,@i int,@j int,@y int,@m int,@tmpval int,<br> @lqj int,@csjfwa1_i bigint,@csjfwa2_i bigint,@csjfwb1_i bigint,@csjfwb2_i bigint ,<br> @cjcsj varchar(20),@mc varchar(20),@sj1 varchar(10),@sj2 varchar(10),@sj3 varchar(10),@sbfw varchar(10),@xbfw varchar(10),@jbsj varchar(10), @cjbsj varchar(10),<br> @bh varchar(20) ,@kh varchar(20) ,@bm varchar(20) ,@xm varchar(20) ,@bc varchar(20) ,@cfield varchar(20), @sqlstr nvarchar(4000),@bcsm varchar(20),<br> @okcs numeric(5,2),@qqcs numeric(5,2) ,@ztfk numeric(5,2),@cdfk numeric(5,2),@cqts numeric(5,2),@qqfk numeric(5,2),@cclx numeric(5,1),@sj numeric(5,1),@sj1a varchar(20),@sj1b varchar(20),@sj2a varchar(20),@sj2b varchar(20),@cdsj int,@ztsj int,@kjyear int,@kjmonth int<br><br> set @i=0 set @j=0 set @csjfwa1_i=0 set @csjfwb1_i=0 set @csjfwa2_i=0 set @csjfwb2_i=0<br> set @kjyear=year(@sdate) set @kjmonth=month(@sdate)<br><br>--初始化<br>CREATE TABLE #kqtjtmp(bh varchar(10), kh varchar(20), xm varchar(10), rq varchar(12),sj1a varchar(10) not null default '', sj1b varchar(10) not null default '', sj2a varchar(10) not null default '', sj2b varchar(10) not null default '', sj3a varchar(10) not null default '' ,sj3b varchar(10) not null default '', cdsj int not null default 0, ztsj int not null default 0, jbsj int not null default 0, sbsj int not null default 0, bcsm varchar(50) not null default '', bm varchar(50) not null default ''  <br>create table #kqhz(cclxdays numeric(10,1), qjdays numeric(10,1), cqdays numeric(10,1), jsdays numeric(10,1), cdfk numeric(10,1), ztfk numeric(10,1), qqfk numeric(10,1)  <br>IF EXISTS (SELECT id FROM tempdb..sysobjects WHERE name = '##count') DROP TABLE ##count create table ##count(id int)<br>select distinct bh,kh,convert(varchar(8),rq,112) rq, REPLACE(CONVERT(char(5), sj, 8), ':', '') sj into #datatmp from rlkh.dbo.yskq where rq between @sdate and @edate order by bh,kh,rq<br>create index rqsj ON #datatmp(rq)<br>create table #sjtmp (sj varchar(20)) <br>SELECT bc, Rq, sj1, sj2, sbfw, xbfw into #kqsj_bb FROM rlkh.dbo.kqsj_bb where rq between @sdate and @edate<br>SELECT xmbh, rq, zl, lx into #qj FROM tl.dbo.qj where rq between @sdate and @edate<br><br>delete from kqhz where kjyear=@kjyear and kjmonth=@kjmonth<br>delete from kqmx where year(rq)=@kjyear and month(rq)=@kjmonth<br>set @ndays= datediff(day,@sdate,@edate) <br><br><br>--根据人事库处理考勤<br>declare Emp_cur cursor for Select bh,kh,bm,xm,bc From rlkh.dbo.employee where kh<>'' order by bh<br>open Emp_cur<br><br>fetch next from Emp_Cur into @bh,@kh,@bm,@xm,@bc<br>while (@@FETCH_STATUS = 0)<br>begin<br> set @j=0<br> while @j<=@ndays <br> begin <br> --开始j<br> set @currqpre=convert(varchar(8),@sdate+@j-1,112)<br> set @currq= convert(varchar(8), @sdate+@j,112) <br> set @currqnext=convert(varchar(8), @sdate+@j+1,112)<br> delete from #sjtmp <br> insert into #sjtmp select rq+sj FROM #datatmp WHERE bh=@bh AND rq between @currqpre and @currqnext <br> INSERT INTO #kqtjtmp (kh,xm,rq,bm,bh) VALUES(@kh,@xm,@currq,@bm,@bh)<br> set @mc=''<br> select @mc=mc from rlkh.dbo.jjr where rq=@currq<br> if @mc<>''<br> update #kqtjtmp set bcsm='(节:'+@mc+')' <br> else<br> begin<br> select @mc=zl+lx from #qj where rq=@currq and xmbh=@bh <br> set @lqj=0<br> if @mc<>''<br> begin<br> update #kqtjtmp set bcsm='(请:'+@mc+')' <br> set @lqj=1<br> end<br> select @sj1=sj1, @sj2=sj2, @sbfw=sbfw, @xbfw=xbfw from #kqsj_bb where bc=@bc and rq=@currq <br> IF EXISTS (SELECT id FROM tempdb..sysobjects WHERE name = '##A') DROP TABLE ##A<br> create table ##A (id int ,a varchar(4),b varchar(4) <br> insert into ##A (id,a,b) values (1,LEFT(@sj1,4),RIGHT(@sj1,4) <br> insert into ##A (id,a,b) values (2,LEFT(@sj2,4),RIGHT(@sj2,4) <br> insert into ##A (id,a,b) values (3,LEFT(@sj3,4),RIGHT(@sj3,4) <br> insert into ##A (id,a,b) values (4,cast(LEFT(@sbfw,3) as integer),cast(RIGHT(@sbfw,3)as integer))<br> insert into ##A (id,a,b) values (5,cast(LEFT(@xbfw,3) as integer),cast(RIGHT(@xbfw,3) as integer))<br> IF LEN(@jbsj)<>4 set @cjbsj='' ELSE set @cjbsj=@jbsj<br> if (select count(sj) from #sjtmp)>0 <br> begin<br> set @i=1<br> while @i<=2<br> begin <br> set @csjfwa1_i=0 set @csjfwb1_i=0 set @csjfwa2_i=0 set @csjfwb2_i=0 set @sjtmp='' <br> if (select len(a)+len(b) from ##A where id=@i) >= 4 <br> begin <br> select @csjfwa1_i=left(a,2)*60+right(a,2)-(select a from ##A where id=4) from ##A where id=@i<br> set @tmpdate=@currq<br> IF @csjfwa1_i<0<br> begin<br> set @tmpdate=@currqpre<br> set @csjfwa1_i=1440+@csjfwa1_i<br> end<br> ELSE IF @csjfwa1_i>1440<br> begin <br> set @tmpdate=@currqnext<br> set @csjfwa1_i=@csjfwa1_i-1440<br> end<br><br> set @csjfwa1=@tmpdate+replace(str(@csjfwa1_i/60, 2),' ','0')+replace(str(@csjfwa1_i % 60 ,2),' ','0')<br> select @csjfwb1_i=left(a,2)*60+right(a,2)+(select b from ##A where id=4) from ##A where id=@i<br> set @tmpdate=@currq<br> <br> IF @csjfwb1_i>1440<br> begin<br> set @tmpdate=@currqnext<br> set @csjfwb1_i=@csjfwb1_i-1440<br> end<br> set @csjfwb1=@tmpdate+replace(str(@csjfwb1_i/60,2),' ' , '0')+replace(str(@csjfwb1_i % 60 ,2),' ','0')<br><br> set @cfield='sj'+str(@i,1)+'a'<br> select @sjtmp=sj from #sjtmp where sj between @csjfwa1 and @csjfwb1<br> if @sjtmp<>'' <br> begin<br> /*set @lsb=1<br> set @y =year(LEFT(@sjtmp,8))+4800-(14- month(LEFT(@sjtmp,8))) / 12<br> set @m =month(LEFT(@sjtmp,8))+12*((14- month(LEFT(@sjtmp,8))) / 12)-3<br> set @nsbsj1= 1440*day(LEFT(@sjtmp,8))+(153*@m+2)/5+365*@y+@y/4-@y/100+@y/400-32045 +cast (SUBSTRing(@sjtmp,9,2) as integer)*60+cast(RIGHT(@sjtmp,2) as integer) <br> */<br> if @sjtmp>@currq+(select a from ##A where id=@i)<br> begin --('+RIGHT(@sjtmp,4)+')<br> set @sqlstr='update #kqtjtmp set '+@cfield+' = ''迟到'' ' <br> exec sp_executesql @sqlstr<br><br> set @tmpval=datediff(minute,@currq+' '+left((select a from ##A where id=@i),2)+':'+right((select a from ##A where id=@i),2)+':00',left(@sjtmp,8)+' '+left(right(@sjtmp,4),2)+':'+right(@sjtmp,2)+':00')<br> update #kqtjtmp set cdsj = cdsj+@tmpval <br> end<br> else<br> begin --(''+RIGHT('+@sjtmp+',4)+'')<br> set @sqlstr='update #kqtjtmp set '+@cfield+' = ''OK'' ' <br> exec sp_executesql @sqlstr<br> end<br> end <br> else<br> begin<br> IF @lqj=0<br> begin<br> set @sqlstr='update #kqtjtmp set '+@cfield+' =''--'' ' <br> exec sp_executesql @sqlstr<br> end <br> end<br> --开始11<br> IF (select a from ##A where id=@i)<>(select b from ##A where id=@i)<br> begin<br> set @csjfwa2_i=cast(LEFT( (select b from ##A where id=@i) ,2) as integer)*60+cast(RIGHT((select b from ##A where id=@i) ,2) as integer)-(select a from ##A where id=5 <br> set @tmpdate1=@sdate+@j<br> IF (select b from ##A where id=@i) < (select a from ##A where id=@i) <br> set @tmpdate1=@tmpdate1+1 <br> set @tmpdate=convert(varchar(8),@tmpdate1,112)<br> IF @csjfwa2_i<0 <br> begin <br> set @tmpdate=convert(varchar(8),@tmpdate1-1,112)<br> set @csjfwa2_i=1440+@csjfwa2_i<br> end <br> set @csjfwa2=@tmpdate+replace(str (@csjfwa2_i/60 ,2),' ','0')+replace(str(@csjfwa2_i % 60 ,2),' ','0')<br> set @csjfwb2_i=cast(LEFT((select b from ##A where id=@i),2) as integer)*60+cast(RIGHT((select b from ##A where id=@i),2) as integer)+(select b from ##A where id=5)<br> set @tmpdate=convert(varchar(8),@tmpdate1,112) <br> IF @csjfwb2_i>1440<br> begin<br> set @tmpdate=convert(varchar(8),@tmpdate1+1,112) <br> set @csjfwb2_i=@csjfwb2_i-1440<br> end <br> set @csjfwb2=@tmpdate+replace(str(@csjfwb2_i/60,2),' ','0')+replace(str (@csjfwb2_i % 60,2),' ','0')<br> set @cfield='sj'+str(@i ,1)+'b'<br> select @sjtmp=sj from #sjtmp where sj between @csjfwa2 and @csjfwb2<br> --开始12<br> if (select count(sj) from #sjtmp where sj between @csjfwa2 and @csjfwb2)>0<br> begin<br> /* IF @lsb=1<br> begin <br> set @nsbsj1= 1440*day(LEFT(@sjtmp,8))+(153*@m+2)/5+365*@y+@y/4-@y/100+@y/400-32045 +<br> cast (SUBSTRing(@sjtmp,9,2) as integer)*60+cast(RIGHT(@sjtmp,2) as integer)-@nsbsj1<br> set @nsbsj1=@nsbsj1 <br> IF @nsbsj1>0<br> set @nsbsj=@nsbsj+@nsbsj1 <br> end */<br> IF @sjtmp<@tmpdate+ (select b from ##A where id=@i)<br> begin<br> set @tmpval=datediff(minute,@tmpdate+' '+left((select b from ##A where id=@i),2)+':'+right((select b from ##A where id=@i),2)+':00',left(@sjtmp,8)+' '+left(right(@sjtmp,4),2)+':'+right(@sjtmp,2)+':00') <br> set @sqlstr='update #kqtjtmp set '+@cfield+' =''早退'' ' --('+RIGHT(@sjtmp,4)+')<br> exec sp_executesql @sqlstr <br> update #kqtjtmp set ztsj =ztsj+@tmpval <br> --set @nztsjh=@nztsjh+@tmpval<br> end<br> else <br> begin --('+RIGHT(@sjtmp,4)+')<br> set @sqlstr='update #kqtjtmp set '+@cfield+' =''OK''' <br> exec sp_executesql @sqlstr<br> end<br> end<br> ELSE<br> begin<br> IF @lqj=0<br> begin<br> set @sqlstr='update #kqtjtmp set '+@cfield+' =''--''' <br> exec sp_executesql @sqlstr<br> end <br> end <br> end<br> end<br> set @i=@i+1<br> end <br> end <br> else<br> begin<br> IF @lqj=0<br> begin<br> set @i=1<br> while @i<=2<br> begin <br> set @sqlstr='update #kqtjtmp set sj'+str(@i ,1)+'a =''--'',sj'+str(@i ,1)+'b =''--'' ' <br> exec sp_executesql @sqlstr <br> set @i=@i+1<br> end<br> end <br> end <br> end <br> --统计<br> set @okcs=0 set @qqcs=0 set @qqfk=0 set @ztfk=0 set @cdfk=0 set @sj=0 set @cclx=0 set @cqts=0<br> select @sj1a=sj1a,@sj1b=sj1b,@sj2a=sj2a,@sj2b=sj2b,@bcsm=bcsm from #kqtjtmp <br> if (@bcsm='(请:轮休整)' or @bcsm='(请:出差整)') begin set @cclx=1 set @cqts=1 end<br> else if (@bcsm='(请:轮休半)' or @bcsm='(请:出差半)') begin set @cclx=0.5 set @cqts=1 end<br> else if (@bcsm='(请:事假整)') begin set @sj=1 set @cqts=0 end<br> else if (@bcsm='(请:事假半)') begin set @sj=0.5 set @cqts=0.5 end<br> else <br> begin <br> if @sj1a in ('ok','迟到','早退') set @okcs=@okcs+1 else if @sj1a='--' set @qqcs=@qqcs+1<br> if @sj1b in ('ok','迟到','早退') set @okcs=@okcs+1 else if @sj1b='--' set @qqcs=@qqcs+1<br> if @sj2a in ('ok','迟到','早退') set @okcs=@okcs+1 else if @sj2a='--' set @qqcs=@qqcs+1<br> if @sj2b in ('ok','迟到','早退') set @okcs=@okcs+1 else if @sj2b='--' set @qqcs=@qqcs+1 <br> if @okcs in (1,2,3) set @cqts=0.5 else if @okcs=4 set @cqts=1 else set @cqts=0<br> if @qqcs in (1,2,3) begin set @qqfk=10*@qqcs set @cqts=1 end else if @qqcs=4 set @cqts=0 <br> end <br> if @cdsj>0 and @cdsj<=5 set @cdfk=1 else if (@cdsj >5 and @cdsj<=15) set @cdfk=2 else if (@cdsj >15 and @cdsj<=30) set @cdfk=5 else set @cdfk=0<br> if @ztsj > 0 and @ztsj<=30 set @ztfk=5 else set @ztfk=0 <br> if exists(select cclxdays from #kqhz <br> update #kqhz set cclxdays=cclxdays+@cclx,qjdays=qjdays+@sj,cqdays=cqdays+@cqts,cdfk=cdfk+@cdfk,ztfk=ztfk+@ztfk,qqfk=qqfk+@qqfk<br> else<br> insert into #kqhz (cclxdays, qjdays, cqdays, jsdays, cdfk, ztfk, qqfk) values(@cclx,@sj,@cqts,0,@cdfk,@ztfk,@qqfk) <br> insert into kqmx (bh, kh, xm, rq, sj1a, sj1b, sj2a, sj2b,sj3a,sj3b,cdsj, ztsj,jbsj,sbsj, bcsm, bm) select * from #kqtjtmp<br> if exists(select id from ##count) update ##count set id=id+1 else insert into ##count (id)values(1)<br> delete from #kqtjtmp<br> set @j=@j+1<br> end --结束j <br> insert into kqhz select @kjyear, @kjmonth, @xm, @bh, @bm, @kh, cclxdays, qjdays, cqdays, jsdays, cdfk, ztfk, qqfk, cdfk+ztfk+qqfk from #kqhz<br> delete from #kqhz<br> fetch next from Emp_Cur into @bh,@kh,@bm,@xm,@bc<br>end<br>close Emp_cur<br>deallocate Emp_cur<br>update kqhz set jsdays=case when bm in ('棉一','棉二','织一','新车间') then 0 else cast((cqdays / 6) as integer) end where kjyear=@kjyear and kjmonth=@kjmonth<br>GO