Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3302656
  • 博文数量: 754
  • 博客积分: 10132
  • 博客等级: 上将
  • 技术积分: 7780
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-14 23:36
文章分类

全部博文(754)

文章存档

2012年(3)

2011年(39)

2010年(66)

2009年(167)

2008年(479)

我的朋友

分类: 数据库开发技术

2008-01-23 21:37:12

/*
有效工作时间计算
用户账号
工作时间:星期一,星期二,星期三,星期四,星期五
  星期一(08:00-12:00,13:00-17:30)
  星期二(08:00-12:00,13:00-17:30)
  星期三(08:00-12:00,13:00-17:30)
  星期四(08:00-12:00,13:00-17:30)
  星期五(08:00-12:00,13:00-17:30)
法定节假日:
 10-01(0)
请假/出差/加班:03-10(1加班,2请假/出差,13:00-17:30)
---------算法一--------
是常规工作日
 是请假
  {...}
 否
  {...}

 是加班
  {...}
 否
  {...}
---------算法二--------
1.常规工作日时间计算有效时间
2.增加加班有效时间(排除常规工作日时间)
3.减去请假/出差无效时间(排除常规工作日时间)
---------算法三:区间合并法---------
-:非工作时段
*:工作时段
@:休假
区间描述说明
区间包含:
 |-----------|*******************|------------|
 |--------------|@@@@@@@@@@@|-----------------|
区间被包含:
 |-----------|*******************|------------|
 |--------|@@@@@@@@@@@@@@@@@@@@@@@@@@|--------|
区间重叠偏左:
 |-----------|*******************|------------|
 |------|@@@@@@@@@@@@@@|----------------------|
区间重叠偏右:
 |-----------|*******************|------------|
 |--------------------|@@@@@@@@@@@@@@@|-------|
区间外:
 |---|************|---------------------------|
 |--------------------|@@@@@@@@@@@|-----------| 
 |------------------------------------------------------------------------|
   1    5
a: |--------|*******************|----------|**********************|---------|
 0     3 
b: |************|------------|*********************|------------------------|
   2
c: |---------------|**************************|-----------------------------|
       4 
d: |---------------------------------|**************************************|
StartTime排序
 0      
b: |************|-----------------------------------------------------------|
       
a: |------------------|*********|-------------------------------------------|
        
c: |------------------------|@@@@@@@@@@@@@@@@@|-----------------------------|
        
d: |---------------------------------------------------|********************|

数据结构设计:
------------------------------------------------------------------------------------------------
TWorkOfWeek    周工作时间(七条固定记录,从1到7分别表示星期一到星期天)
 int  ID  自动编号
 int    WeekDay  1-7:星期一到星期天
 int    RecessFullDay 是否全天休假(1:全休)
THoriday    公共特殊日期(假期,调休)
 int  ID  自动编号
 datetime  SDate  日期(不含时间部分或者时分秒为“00:00:00”)
 int    RecessFullDay 是否全天休假(1:全休)
TSpecialDay    个人特殊日工作/非工作日:请假/休假/加班/年假
 int  ID  自动编号
 varchar(16) LoginName 账号名称
 datetime  SDate  日期(不含时间部分或者时分秒为“00:00:00”)
 int    RecessFullDay 是否全天休假(1:全休)
TWorkOfPeriodTime 天工作时间段
 int  ID  自动编号
 int  TimeKind 时间段类型:0或空-特殊日,1-工作日,2-公共假期
 int  DayID  日期ID(特殊日,工作日,公共假期)
 int  IsWork  是否工作(1:是工作)
 int  WorkKind 工作类型:工作日/法定假日/请假/休假/加班/年假
 int  StartHour 开始时间-时
 int  StartMinute 开始时间-分
 int  EndHour  结束时间-时
 int  EndMinute 结束时间-分
------------------------------------------------------------------------------------------------
*/
--if exists(select * from sysobjects where type='FN' and name='fn_CaculateWorkTimeValid')
--drop function fn_CacualteWorkTimeValid
--go
--use manageproblem
--go
--SET DATEFIRST 1 --星期一为第一天
--declare @LoginName varchar(30)
--declare @StartTime datetime
--declare @EndTime datetime
--select @LoginName = '3002'
--select @StartTime = '2007-03-09 11:59:10'
--select @EndTime =  '2007-03-09 13:00:11'
--185 2007-03-01 16:29:19.930 2007-03-02 16:13:41.693 254

--create function fn_CaculateWorkTimeValid(
CREATE function fn_CaculateWorkTimeValid(
 @LoginName varchar(30),
 @StartTime datetime ,
 @EndTime datetime
)
returns int
as
begin
 /*
 --初始化 TWorkOfWeek
 declare TWTWorkOfWeek table (
  [ID]   int, --自动编号
  [WeekDay]  int, --0-6:星期一到星期天
  [RecessFullDay] bit --是否全天休假(1:全休)
  )
 --初始化 THoriday
 declare TWTHoriday table (
  [ID]  int,  --自动编号
  [SDate]  datetime, --月份(不含时间部分或者时分秒为“00:00:00”)
  [RecessFullDay] bit  --是否全天休假(1:全休)
  )
 --初始化 TSpecialDay
 declare TWTSpecialDay table (
  [ID]  int,  --自动编号
  [LoginName] varchar(16), --账号名称
  [SDate]  datetime, --日期(不含时间部分或者时分秒为“00:00:00”)
  [RecessFullDay] bit  --是否全天休假(1:全休)
  )
 --初始化 TWorkOfPeriodTime
 declare TWTWorkOfPeriodTime table (
  [ID]  int,  --自动编号
  [TimeKind] int,  --时间段类型:0或空-特殊日,1-工作日,2-公共假期
  [DayID]  int,  --日期ID(特殊日,工作日,公共假期)
  [IsWork] bit,  --是否工作(1:是工作)
  [WorkKind] int,  --工作类型:工作日/法定假日/请假/休假/加班/年假
  [StartHour] int,  --开始时间-时
  [StartMinute] int,  --开始时间-分
  [EndHour] int,  --结束时间-时
  [EndMinute] int  --结束时间-分
  )
 */
 --初始化有效时间计算的时间区间
 declare @TWorkOfPeriodTimeArea table (
   SDate  datetime,
   StartHour  int,
   StartMinute  int,
   EndHour  int,
   EndMinute  int
  )
 
 ------ 测试数据 实例账号 amdin -------
 /*
 --工作日设置TWorkOfWeek
 insert into TWTWorkOfWeek values(1,1,0) --工作日 星期一
 insert into TWTWorkOfWeek values(2,2,0) --工作日
 insert into TWTWorkOfWeek values(3,3,0) --工作日
 insert into TWTWorkOfWeek values(4,4,0) --工作日
 insert into TWTWorkOfWeek values(5,5,0) --工作日
 insert into TWTWorkOfWeek values(6,6,1) --非工作日
 insert into TWTWorkOfWeek values(7,7,1) --非工作日
 --公共假日设置THoriday
 insert into TWTHoriday values(1,'2007-03-05',1) --公共假期,全休
 insert into TWTHoriday values(2,'2007-03-07',0) --公共假期,半休
 --特殊日设置TSpecialDay
 insert into TWTSpecialDay values(1,'admin','2007-03-08',1) --个人请假,全休
 insert into TWTSpecialDay values(2,'admin','2007-03-09',0) --个人请假,半休
 insert into TWTSpecialDay values(3,'admin','2007-03-10',0) --个人加班
 --时间段设置TWorkOfPeriodTime
 --工作日
 insert into TWTWorkOfPeriodTime values(01,1,1,1,1,08,30,12,00)
 insert into TWTWorkOfPeriodTime values(02,1,1,1,1,13,00,17,30)
 insert into TWTWorkOfPeriodTime values(03,1,2,1,1,08,30,12,00)
 insert into TWTWorkOfPeriodTime values(04,1,2,1,1,13,00,17,30)
 insert into TWTWorkOfPeriodTime values(05,1,3,1,1,08,30,12,00)
 insert into TWTWorkOfPeriodTime values(06,1,3,1,1,13,00,17,30)
 insert into TWTWorkOfPeriodTime values(07,1,4,1,1,08,30,12,00)
 insert into TWTWorkOfPeriodTime values(08,1,4,1,1,13,00,17,30)
 insert into TWTWorkOfPeriodTime values(09,1,5,1,1,08,30,12,00)
 insert into TWTWorkOfPeriodTime values(10,1,5,1,1,13,00,17,30)
 insert into TWTWorkOfPeriodTime values(11,1,6,0,1,08,30,12,00)
 insert into TWTWorkOfPeriodTime values(12,1,6,0,1,13,00,17,30)
 insert into TWTWorkOfPeriodTime values(13,1,7,0,1,08,30,12,00)
 insert into TWTWorkOfPeriodTime values(14,1,7,0,1,13,00,17,30)
 --公共假期
 insert into TWTWorkOfPeriodTime values(15,2,1,0,2,08,30,12,00) --星期四,3.8,公共假期放半天假
 insert into TWTWorkOfPeriodTime values(16,2,1,0,2,13,00,17,30) --星期四,3.8,公共假期放半天假
 insert into TWTWorkOfPeriodTime values(17,2,2,0,2,13,00,17,30) --星期四,3.8,公共假期放半天假
 --特殊日
 insert into TWTWorkOfPeriodTime values(18,0,1,0,5,08,00,12,00) --个人请假,全休
 insert into TWTWorkOfPeriodTime values(19,0,1,0,5,13,00,17,30) --个人请假,全休
 insert into TWTWorkOfPeriodTime values(20,0,2,0,5,08,30,12,00) --个人请假
 insert into TWTWorkOfPeriodTime values(21,0,3,1,3,08,30,12,00) --个人加班
 */
 declare @returnVal nvarchar(1000)
 select @ReturnVal = ''
 --------- 有效时间计算 ------------
 declare @nAllValidWorkTime int --有效工作时间(分钟)
 declare @nValidWorkTime  int --工作日时间累加
 declare @nValidHoridayTime int --公共特殊日期工作时间累加
 declare @nInValidHoridayTime int --公共特殊日期非工作时间累加
 declare @nValidSpecialTime int --个人特殊日期工作时间累加
 declare @nInVaidSpecialTime int --个人特殊日期非工作时间累加
 declare @i int   --循环计数器
 declare @tStartTimeSplit datetime --时间分离开始时间
 declare @tEndTimeSplit datetime --时间分离结束时间
 declare @nWeekDay int  --当前日期的星期几
 declare @ID   int
 declare @Date   datetime --日期(不含时间部分)
 
 --时间分离
 declare @nDayDif int  --开始时间 和 结束时间 间隔天数
 select @nDayDif = datediff(day,@StartTime,@EndTime)
 select @i = 0
 while(@i<)
  begin
  --分析个日期的时间段
  if(@i=0)
    begin
   select @tStartTimeSplit = @StartTime
   select @tEndTimeSplit = convert(varchar(5),year(@StartTime)) + '-' + convert(varchar(5),month(@StartTime)) + '-' + convert(varchar(5),day(@StartTime)) + ' 23:59'
   end
  else
    begin
   if(@i=@nDayDif)
    begin
    select @tStartTimeSplit = convert(varchar(5),year(@EndTime)) + '-' + convert(varchar(5),month(@EndTime)) + '-' + convert(varchar(5),day(@EndTime))
    select @tEndTimeSplit = @EndTime
    end
   else
    begin
    select @tStartTimeSplit = dateadd(day,@i,@StartTime)
    select @tStartTimeSplit = convert(varchar(5),year(@tStartTimeSplit)) + '-' + convert(varchar(5),month(@tStartTimeSplit)) + '-' + convert(varchar(5),day(@tStartTimeSplit))
    select @tEndTimeSplit = convert(varchar(5),year(@tStartTimeSplit)) + '-' + convert(varchar(5),month(@tStartTimeSplit)) + '-' + convert(varchar(5),day(@tStartTimeSplit)) + ' 23:59'
    end
   end
  declare @IsAreaBaoHan bit --区间包含
  declare @IsAreaBBaoHan bit --区间被包含
  declare @IsAreaLeft bit  --区间重叠偏左
  declare @IsAreaRight bit --区间重叠偏右
  declare @IsAreaOut bit  --区间外
  select @Date = convert(varchar(5),year(@tStartTimeSplit)) + '-' + convert(varchar(5),month(@tStartTimeSplit)) + '-' + convert(varchar(5),day(@tStartTimeSplit))
  --初始化各时间技术参数
  select @nValidWorkTime = 0  --工作日时间累加
  select @nValidHoridayTime = 0  --公共特殊日期工作时间累加
  select @nInValidHoridayTime = 0  --公共特殊日期非工作时间累加
  select @nValidSpecialTime = 0  --个人特殊日期工作时间累加
  select @nInVaidSpecialTime = 0  --个人特殊日期非工作时间累加  
  
  --当前日期为星期几
   偏移量,校正(@@DATEFIRST-1)+datepart(weekday,'2007-3-20')
  --取模((@@DATEFIRST-1)+datepart(weekday,'2007-3-20')) % 7
  --select @nWeekDay = DATEPART(weekday,@Date)
  select @nWeekDay = ((@@DATEFIRST-1)+datepart(weekday,@Date)) % 7
  --游标数据集存储变量
  declare @CurID  int  --自动编号
  declare @CurTimeKind int  --时间段类型:0或空-特殊日,1-工作日,2-公共假期
  declare @CurDayID int  --日期ID(特殊日,工作日,公共假期)
  declare @CurIsWork int  --是否工作(1:是工作)
  declare @CurWorkKind int  --工作类型:工作日/法定假日/请假/休假/加班/年假
  declare @CurStartHour int  --开始时间-时
  declare @CurStartMinute int  --开始时间-分
  declare @CurEndHour int  --结束时间-时
  declare @CurEndMinute int  --结束时间-分
  
  --debug--
  /*
  SELECT ID,TimeKind,DayID,IsWork,WorkKind,StartHour,StartMinute,EndHour,EndMinute
   FROM TWTWorkOfPeriodTime
  select @Date
  select @nWeekDay
  select * from TWTWorkOfWeek where and RecessFullDay<>1
  select * from TWTHoriday where and RecessFullDay<>1
  select * from TWTSpecialDay where and and RecessFullDay<>1
  SELECT ID,TimeKind,DayID,IsWork,WorkKind,StartHour,StartMinute,EndHour,EndMinute
   FROM TWTWorkOfPeriodTime
   where  ((TimeKind=1 and DayID in(select ID from TWTWorkOfWeek where and RecessFullDay<>1)) --工作日
         or (TimeKind=2 and DayID in(select ID from TWTHoriday where and RecessFullDay<>1)) --公共特殊日期(假日,调休)
         or (TimeKind=0 and DayID in(select ID from TWTSpecialDay where and and RecessFullDay<>1)) ----个人特殊日期(请假,加班...)
   ) and IsWork=1    
  --/debug--
  */
  --工作时间游标
  DECLARE GetTWorkOfPeriodTime CURSOR FOR
  SELECT ID,TimeKind,DayID,IsWork,WorkKind,StartHour,StartMinute,EndHour,EndMinute
   FROM TWTWorkOfPeriodTime
   where  ((TimeKind=1 and DayID in(select ID from TWTWorkOfWeek where and RecessFullDay<>1)) --工作日
         or (TimeKind=2 and DayID in(select ID from TWTHoriday where and RecessFullDay<>1)) --公共特殊日期(假日,调休)
         or (TimeKind=0 and DayID in(select ID from TWTSpecialDay where and and RecessFullDay<>1)) ----个人特殊日期(请假,加班...)
   ) and IsWork=1
  OPEN GetTWorkOfPeriodTime
  FETCH NEXT FROM GetTWorkOfPeriodTime
  INTO
  @CurID,  --自动编号
  @CurTimeKind, --时间段类型:0或空-特殊日,1-工作日,2-公共假期
  @CurDayID, --日期ID(特殊日,工作日,公共假期)
  @CurIsWork, --是否工作(1:是工作)
  @CurWorkKind, --工作类型:工作日/法定假日/请假/休假/加班/年假
  @CurStartHour, --开始时间-时
  @CurStartMinute,--开始时间-分
  @CurEndHour, --结束时间-时
  @CurEndMinute --结束时间-分
  WHILE @@FETCH_STATUS = 0
  BEGIN
   select @IsAreaBaoHan = 0
   select @IsAreaBBaoHan = 0
   select @IsAreaLeft = 0
   select @IsAreaRight = 0
   select @IsAreaOut = 0
   --区间包含,不添加记录
   --debug--
   /*
   select '---------------------------'
   select 'Date:' + convert(varchar(20),@Date)
   select * from @TWorkOfPeriodTimeArea
   */
   --/debug--
   if exists(select * from @TWorkOfPeriodTimeArea
    where ((StartHour<@CurStartHour) or ( and StartMinute<))
     and
          ((EndHour>@CurEndHour) or ( and EndMinute>=@CurEndMinute))
     and
          
    )
     begin
    select @IsAreaBaoHan = 1
    --debug--
    /*
    select '区间包含'
    select * from @TWorkOfPeriodTimeArea
    where ((StartHour<@CurStartHour) or ( and StartMinute<))
     and
          ((EndHour>@CurEndHour) or ( and EndMinute>=@CurEndMinute))
     and
          
    select convert(varchar(2),@CurStartHour) + ':' + convert(varchar(2),@CurStartMinute)
    select convert(varchar(2),@CurEndHour) + ':' + convert(varchar(2),@CurEndMinute)
    */
    --/debug--
     end
   --区间被包含,删除区间内的记录,然后添加新记录
   if exists(select * from @TWorkOfPeriodTimeArea
    where ((StartHour>@CurStartHour) or ( and StartMinute>=@CurStartMinute))
     and
          ((EndHour<@CurEndHour) or ( and EndMinute<))
     and
          
    )
      begin
    --debug--
    --select '区间被包含'
    --/debug--    
    select @IsAreaBBaoHan = 1
    --删除区间内的记录
    delete from @TWorkOfPeriodTimeArea
    where ((StartHour>@CurStartHour) or ( and StartMinute>=@CurStartMinute))
     and
          ((EndHour<@CurEndHour) or ( and EndMinute<))
     and
          
    --添加新记录
    insert into @TWorkOfPeriodTimeArea values(@Date,@CurStartHour,@CurStartMinute,@CurEndHour,@CurEndMinute)
      end
   --区间重叠偏左,合并区间(更新StartHour,StartMinute,EndHour,EndMinute)
   if exists(select * from @TWorkOfPeriodTimeArea
      where ((StartHour>@CurStartHour) or ( and StartMinute>@CurStartMinute))
       and
     ((Starthour<@CurEndHour) or ( and StartMinute<@CurEndMinute))
       and
           
    )
     begin
    --debug--
    --select '区间重叠偏左'
    --/debug--
    select @IsAreaLeft = 1
    update @TWorkOfPeriodTimeArea Set
      where ((StartHour>@CurStartHour) or ( and StartMinute>@CurStartMinute))
       and
     ((Starthour<@CurEndHour) or ( and StartMinute<@CurEndMinute))
       and
           
     end
   --区间重叠偏右,合并区间后添加新记录,把旧记录删除
   if exists(select * from @TWorkOfPeriodTimeArea
      where ((EndHour>@CurStartHour) or ( and EndMinute>@CurStartMinute))
       and
     ((EndHour<@CurEndHour) or ( and EndMinute<@CurEndMinute))
       and
           
    )
     begin
    --debug--
    --select '区间重叠偏右'
    --/debug--
    select @IsAreaRight = 1
    update @TWorkOfPeriodTimeArea Set
      where ((EndHour>@CurStartHour) or ( and EndMinute>@CurStartMinute))
       and
     ((EndHour<@CurEndHour) or ( and EndMinute<@CurEndMinute))
       and
           
     end
   --区间外
   if not(@IsAreaBaoHan=1 or @IsAreaBBaoHan=1 or @IsAreaLeft=1 or @IsAreaRight=1)
    select @IsAreaOut=1
   
   if(@IsAreaOut=1)
     begin
    --debug--
    --select 'out'
    --/debug--
    --添加新记录
    insert into @TWorkOfPeriodTimeArea values(@Date,@CurStartHour,@CurStartMinute,@CurEndHour,@CurEndMinute)
     end
   FETCH NEXT FROM GetTWorkOfPeriodTime
   INTO
   @CurID,  --自动编号
   @CurTimeKind, --时间段类型:0或空-特殊日,1-工作日,2-公共假期
   @CurDayID, --日期ID(特殊日,工作日,公共假期)
   @CurIsWork, --是否工作(1:是工作)
   @CurWorkKind, --工作类型:工作日/法定假日/请假/休假/加班/年假
   @CurStartHour, --开始时间-时
   @CurStartMinute,--开始时间-分
   @CurEndHour, --结束时间-时
   @CurEndMinute --结束时间-分
  END
  CLOSE GetTWorkOfPeriodTime
  DEALLOCATE GetTWorkOfPeriodTime
 --Debug--
 --select * from TWTWorkOfPeriodTime
 --select * from @TWorkOfPeriodTimeArea
 --/Debug--
  --非工作时间游标
  DECLARE GetTNotWorkOfPeriodTime CURSOR FOR
  SELECT ID,TimeKind,DayID,IsWork,WorkKind,StartHour,StartMinute,EndHour,EndMinute
   FROM TWTWorkOfPeriodTime
   where  ((TimeKind=2 and DayID in(select ID from TWTHoriday where )) --公共特殊日期(假日,调休)
         or (TimeKind=0 and DayID in(select ID from TWTSpecialDay where and )) ----个人特殊日期(请假,加班...)
   ) and IsWork<>1
    
  OPEN GetTNotWorkOfPeriodTime
  FETCH NEXT FROM GetTNotWorkOfPeriodTime
  INTO
  @CurID,  --自动编号
  @CurTimeKind, --时间段类型:0或空-特殊日,1-工作日,2-公共假期
  @CurDayID, --日期ID(特殊日,工作日,公共假期)
  @CurIsWork, --是否工作(1:是工作)
  @CurWorkKind, --工作类型:工作日/法定假日/请假/休假/加班/年假
  @CurStartHour, --开始时间-时
  @CurStartMinute,--开始时间-分
  @CurEndHour, --结束时间-时
  @CurEndMinute --结束时间-分
  WHILE @@FETCH_STATUS = 0
  BEGIN
   --在区间外,删除时间段
   if exists(select * from @TWorkOfPeriodTimeArea
    where ((StartHour>@CurStartHour) or ( and StartMinute>=@CurStartMinute))
     and
          ((EndHour<@CurEndHour) or ( and EndMinute<))
     and
          
    )
      begin
    --删除区间内的记录
    delete from @TWorkOfPeriodTimeArea
    where ((StartHour>@CurStartHour) or ( and StartMinute>=@CurStartMinute))
     and
          ((EndHour<@CurEndHour) or ( and EndMinute<))
     and
          
      end
   --在区间内,分割记录
   if exists(select * from @TWorkOfPeriodTimeArea
    where ((StartHour<@CurStartHour) or ( and StartMinute<))
     and
          ((EndHour>@CurEndHour) or ( and EndMinute>=@CurEndMinute))
     and
          
    )
     begin
    declare @StartHourArea int
    declare @StartMinuteArea int
    declare @EndHourArea int
    declare @EndMinuteArea int
    DECLARE GetTWorkOfPeriodTimeArea CURSOR FOR
    SELECT StartHour,StartMinute,EndHour,EndMinute
     FROM @TWorkOfPeriodTimeArea
     where ((StartHour<@CurStartHour) or ( and StartMinute<))
       and
           ((EndHour>@CurEndHour) or ( and EndMinute>=@CurEndMinute))
       and
          
      
    OPEN GetTWorkOfPeriodTimeArea
    FETCH NEXT FROM GetTWorkOfPeriodTimeArea
    INTO @StartHourArea ,@StartMinuteArea,@EndHourArea,@EndMinuteArea
    CLOSE GetTWorkOfPeriodTimeArea
    DEALLOCATE GetTWorkOfPeriodTimeArea
    --删除记录
    delete FROM @TWorkOfPeriodTimeArea
     where ((StartHour<@CurStartHour) or ( and StartMinute<))
       and
           ((EndHour>@CurEndHour) or ( and EndMinute>=@CurEndMinute))
       and
          
    --左边记录
    if ((@StartHourArea<@CurStartHour) or (@StartHourArea=@CurStartHour and @StartMinuteArea<@CurStartMinute))
       begin
     insert into @TWorkOfPeriodTimeArea values(@Date,@StartHourArea,@StartMinuteArea,@CurStartHour,@CurStartMinute)
       end
    --右边记录
    if ((@EndHourArea>@CurEndHour) or (@EndHourArea=@CurEndHour and @EndMinuteArea>@CurEndMinute))
       begin
     insert into @TWorkOfPeriodTimeArea values(@Date,@CurEndHour,@CurEndMinute,@EndHourArea,@EndMinuteArea)
       end
     end
   --区间重叠偏左,合并区间(更新StartHour,StartMinute,EndHour,EndMinute)
   if exists(select * from @TWorkOfPeriodTimeArea
      where ((StartHour>@CurStartHour) or ( and StartMinute>@CurStartMinute))
       and
     ((Starthour<@CurEndHour) or ( and StartMinute<@CurEndMinute))
       and
           
    )
     begin
    update @TWorkOfPeriodTimeArea Set
      where ((StartHour>@CurStartHour) or ( and StartMinute>@CurStartMinute))
       and
     ((Starthour<@CurEndHour) or ( and StartMinute<@CurEndMinute))
       and
           
     end
   else
     --区间重叠偏右,合并区间(更新StartHour,StartMinute,EndHour,EndMinute)
     if exists(select * from @TWorkOfPeriodTimeArea
      where ((EndHour>@CurStartHour) or ( and EndMinute>@CurStartMinute))
       and
     ((EndHour<@CurEndHour) or ( and EndMinute<@CurEndMinute))
       and
           
    )
       begin
    update @TWorkOfPeriodTimeArea Set
      where ((EndHour>@CurStartHour) or ( and EndMinute>@CurStartMinute))
       and
     ((EndHour<@CurEndHour) or ( and EndMinute<@CurEndMinute))
       and
           
       end
   FETCH NEXT FROM GetTNotWorkOfPeriodTime
   INTO
   @CurID,  --自动编号
   @CurTimeKind, --时间段类型:0或空-特殊日,1-工作日,2-公共假期
   @CurDayID, --日期ID(特殊日,工作日,公共假期)
   @CurIsWork, --是否工作(1:是工作)
   @CurWorkKind, --工作类型:工作日/法定假日/请假/休假/加班/年假
   @CurStartHour, --开始时间-时
   @CurStartMinute,--开始时间-分
   @CurEndHour, --结束时间-时
   @CurEndMinute --结束时间-分
  END
  CLOSE GetTNotWorkOfPeriodTime
  DEALLOCATE GetTNotWorkOfPeriodTime
  --1.常规工作日时间计算有效时间
  --2.增加加班有效时间(排除常规工作日时间)
  --3.减去请假/出差无效时间(排除常规工作日时间)
  select @i=@i + 1
  end
 select @nValidWorkTime = (select sum(datediff(minute,
       convert(varchar(2),StartHour) + ':' + convert(varchar(2),StartMinute),
       convert(varchar(2),EndHour) + ':' + convert(varchar(2),EndMinute)
                     )
            ) as ValidWorkTime
      from @TWorkOfPeriodTimeArea 
     )
 --提取开始时间、结束时间的时、分
 declare @StartHour int
 declare @StartMinute int
 declare @EndHour int
 declare @EndMinute int
 select @StartHour = datepart(hour,@StartTime)
 select @StartMinute = datepart(minute,@StartTime)
 select @EndHour = datepart(Hour,@EndTime)
 select @EndMinute = datepart(Minute,@EndTime)
 declare @MinDateTime datetime --最小时间
 declare @MaxDateTime datetime --最大时间
 --计算区间包含/偏移交叉的最小时间
 select @MinDateTime = (select min(convert(datetime,convert(varchar(5),year(SDate)) + '-' + convert(varchar(5),month(SDate)) + '-' + convert(varchar(5),day(SDate)) + ' '
    + convert(varchar(2),StartHour) + ':' + convert(varchar(2),StartMinute))) as MinDateTime
    from @TWorkOfPeriodTimeArea
      where ((@StartHour>StartHour) or ((@StartHour=StartHour) and @StartMinute>=StartMinute))
        and
            ((@StartHour          )
 --计算区间包含/偏移交叉的最大时间
 select @MaxDateTime = (select max(convert(datetime,convert(varchar(5),year(SDate)) + '-' + convert(varchar(5),month(SDate)) + '-' + convert(varchar(5),day(SDate)) + ' '
    + convert(varchar(2),EndHour) + ':' + convert(varchar(2),EndMinute))) as MaxDateTime
    from @TWorkOfPeriodTimeArea
      where ((@EndHour>StartHour) or ((@EndHour=StartHour) and @EndMinute>=StartMinute))
        and
            ((@EndHour          )
 --纠正计算数据,截取头尾部分时间
 declare @MinDateTimeDif int --最小时间 和 开始时间 差
 declare @MaxDateTimeDif int --最大时间 和 结束时间 差
 
 declare @nAreaOutMinuteDifCount int  --区间外的时间总数
 --计算区间外的时间总数
 select @nAreaOutMinuteDifCount = (select sum(datediff(minute,convert(nvarchar(2),StartHour) + ':' + convert(nvarchar(2),StartMinute)
     ,convert(nvarchar(2),EndHour) + ':' + convert(nvarchar(2),EndMinute)
     )) as nMinuteDifCount
      from @TWorkOfPeriodTimeArea
      where (
      ((EndHour<@StartHour) or (() and EndMinute<@StartMinute))
      and SDate=convert(nvarchar(5),year(@StartTime)) + '-' + convert(nvarchar(5),month(@StartTime)) + '-' + convert(nvarchar(5),day(@StartTime)) --区间外时间(开始时间时间之日)
            )
        or
            (
      ((StartHour>@EndHour) or (() and StartMinute>@EndMinute))
      and SDate=convert(nvarchar(5),year(@EndTime)) + '-' + convert(nvarchar(5),month(@EndTime)) + '-' + convert(nvarchar(5),day(@EndTime)) --区间外时间(结束时间之日)
            )
       )
 select @nAreaOutMinuteDifCount = (select isnull(@nAreaOutMinuteDifCount,0) as c) --如果为空,设零
 if @StartTime>@MinDateTime --开始时间大于最小时间,减去开始部分多余的无效时间
  select @nValidWorkTime = @nValidWorkTime - datediff(minute,@MinDateTime,@StartTime)
 if @EndTime<@MaxDateTime --结束时间小于最大时间,减去结束部分多余的无效时间
  select @nValidWorkTime = @nValidWorkTime - datediff(minute,@EndTime,@MaxDateTime)
 select @nValidWorkTime = @nValidWorkTime - @nAreaOutMinuteDifCount --减去区间外的时间
 --Debug--  
 --select * from TWTWorkOfPeriodTime
 /*
 select * from @TWorkOfPeriodTimeArea
 select @MinDateTime
 select @StartTime
 select @EndTime
 select @MaxDateTime
 select @returnVal = convert(varchar(100),@nValidWorkTime)
 select @returnVal
 */
 
 --/Debug--
 select @nValidWorkTime  = (select isnull(@nValidWorkTime,0) as c)
-- select @nValidWorkTime
 return @nValidWorkTime 
end

 
阅读(8216) | 评论(0) | 转发(0) |
0

上一篇:翻页Sql

下一篇:五子棋算法

给主人留下些什么吧!~~