从逻辑上说,这应该可行,但它可能不是最优雅的解决方案。
在创建了一些样本数据之后,我收集了所有'可疑'日,包括已知病假,已知假日和周末,与病假或假期相邻。然后,我确定每组连续日的开始和结束日期,并且为每个员工计算包含病假的范围的开始日期。
/***** SAMPLE DATA *****/
declare @sick table (
empid int,
sick datetime
)
declare @holiday table (
holiday datetime
)
/* Example 1 */
insert into @sick values (1,'2010/01/04'); /* Mon */
insert into @sick values (1,'2010/01/05'); /* Tue */
/* Example 2 */
insert into @sick values (1,'2010/01/15'); /* Fri */
insert into @sick values (1,'2010/01/18'); /* Mon */
/* Example 3 */
insert into @sick values (1,'2010/01/21'); /* Thu */
insert into @holiday values('2010/01/22'); /* Fri */
insert into @sick values (1,'2010/01/25'); /* Mon */
/* Extra Examples */
insert into @sick values (3,'2010/01/08');
insert into @sick values (2,'2010/01/08');
insert into @holiday values ('2010/01/11');
insert into @sick values (3,'2010/01/20');
insert into @sick values (3,'2010/01/21');
/* Extra Holiday */
insert into @holiday values ('2010/02/05');
/***** SAMPLE DATA *****/
/* First a CTE to gather all of the 'suspect' days together
including known sick days, known holidays and weekends
that are adjacent to either a sick day or a holiday */
with suspectdays as (
/* Start with all Sick days */
select
empid,
sick dt,
'sick' [type]
from
@sick
/* Add all Saturdays following a sick Friday */
union
select
empid,
DATEADD(day,1,sick) dt,
'weekend' [type]
from
@sick
where
(DATEPART(WEEKDAY,sick) + @@DATEFIRST) % 7 = 6
/* Add all Sundays following a sick Friday */
union
select
empid,
DATEADD(day,2,sick) dt,
'weekend' [type]
from
@sick
where
(DATEPART(WEEKDAY,sick) + @@DATEFIRST) % 7 = 6
/* Add all Sundays preceding a sick Monday */
union
select
empid,
DATEADD(day,-1,sick) dt,
'weekend' [type]
from
@sick
where
(DATEPART(WEEKDAY,sick) + @@DATEFIRST) % 7 = 2
/* Add all Saturdays preceding a sick Monday */
union
select
empid,
DATEADD(day,-2,sick) dt,
'weekend' [type]
from
@sick
where
(DATEPART(WEEKDAY,sick) + @@DATEFIRST) % 7 = 2
/* Add all Holidays */
union
select
empid,
holiday dt,
'holiday' [type]
from
@holiday,
(select distinct empid from @sick) as a
/* Add all Saturdays following a holiday Friday */
union
select
empid,
DATEADD(day,1,holiday) dt,
'weekend' [type]
from
@holiday,
(select distinct empid from @sick) as a
where
(DATEPART(WEEKDAY,holiday) + @@DATEFIRST) % 7 = 6
/* Add all Sundays following a holiday Friday */
union
select
empid,
DATEADD(day,2,holiday) dt,
'weekend' [type]
from
@holiday,
(select distinct empid from @sick) as a
where
(DATEPART(WEEKDAY,holiday) + @@DATEFIRST) % 7 = 6
/* Add all Sundays preceding a holiday Monday */
union
select
empid,
DATEADD(day,-1,holiday) dt,
'weekend' [type]
from
@holiday,
(select distinct empid from @sick) as a
where
(DATEPART(WEEKDAY,holiday) + @@DATEFIRST) % 7 = 2
/* Add all Saturdays preceding a holiday Monday */
union
select
empid,
DATEADD(day,-2,holiday) dt,
'weekend' [type]
from
@holiday,
(select distinct empid from @sick) as a
where
(DATEPART(WEEKDAY,holiday) + @@DATEFIRST) % 7 = 2
),
/* Now a CTE to identify the start and end of each
group of consecutive days for each employee */
suspectranges as (
select distinct
sd.empid,
( select
max(dt)
from
suspectdays
where
empid = sd.empid and
DATEADD(day,-1,dt) not in (select dt from suspectdays where empid = sd.empid) and
dt <= sd.dt
) rangeStart,
( select
min(dt)
from
suspectdays
where
empid = sd.empid and
DATEADD(day,1,dt) not in (select dt from suspectdays where empid = sd.empid) and
dt >= sd.dt
) rangeEnd
from
suspectdays sd
)
/* For each employee count the start dates of ranges that contain a sick day */
select
empid,
COUNT(rangeStart) SickIncidents
from
suspectranges sr
where
exists (select * from suspectdays where dt between sr.rangeStart and sr.rangeEnd and empid=sr.empid and type='sick')
group by
empid
对于我创建的样本数据,这里的结果。
empid SickIncidents
----------- -------------
1 3
2 1
3 2
这是在不知道必要的数据库表的模式的情况下难以回答!如果您还没有桌子,您需要先询问如何存储这些信息。如果你有表格,更新你的文章以包含它们。 – 2010-06-04 20:30:05
为了简化计算 - tbl_emp - EMPID,empname, tbl_sick - EMPID,sickdate, tbl_holiday - holidate 请让我知道如果你需要更多的信息。谢谢 – Bill 2010-06-04 20:36:58
我会撤回所有数据,并在Java中执行,因为编写长SQL会伤害我的头;) – bwawok 2010-06-05 02:47:34