2016-11-23 47 views
0

我有一张名为activities的表格,用于存储员工正在进行的活动。它存储简单的信息,例如他们是否在工作,或者他们是否有不同类型的休假,例如,年假,病假,体恤假等。该表格存储员工编号,活动类型和活动日期。在一天内只能发生一种活动,只有正常工作的日子才会有活动归因于他们。例如,如果员工是星期一至星期五的工作人员并且每年休假一周,则表中不包括周末日期,因为他们不是员工通常工作的日子。查找类似连续记录的开始日期

下面是一个示例表:

 

╔══════════╦════════════╦══════════════╗ 
║ Employee ║ Date ║ Activity ║ 
╠══════════╬════════════╬══════════════╣ 
║ 12345 ║ 25/11/2016 ║ Work   ║ 
║ 12345 ║ 24/11/2016 ║ Work   ║ 
║ 12345 ║ 23/11/2016 ║ Work   ║ 
║ 12345 ║ 22/11/2016 ║ Work   ║ 
║ 12345 ║ 21/11/2016 ║ Work   ║ 
║ 12345 ║ 18/11/2016 ║ Work   ║ 
║ 12345 ║ 17/11/2016 ║ Work   ║ 
║ 12345 ║ 16/11/2016 ║ Work   ║ 
║ 12345 ║ 15/11/2016 ║ Sick Leave ║ 
║ 12345 ║ 14/11/2016 ║ Sick Leave ║ 
║ 12345 ║ 11/11/2016 ║ Sick Leave ║ 
║ 12345 ║ 10/11/2016 ║ Work   ║ 
║ 12345 ║ 9/11/2016 ║ Work   ║ 
║ 12345 ║ 8/11/2016 ║ Work   ║ 
║ 12345 ║ 7/11/2016 ║ Work   ║ 
║ 12345 ║ 4/11/2016 ║ Work   ║ 
║ 12345 ║ 3/11/2016 ║ Sick Leave ║ 
║ 12345 ║ 2/11/2016 ║ Sick Leave ║ 
║ 12345 ║ 1/11/2016 ║ Work   ║ 
║ 12345 ║ 31/10/2016 ║ Work   ║ 
║ 67890 ║ 25/11/2016 ║ Annual Leave ║ 
║ 67890 ║ 24/11/2016 ║ Annual Leave ║ 
║ 67890 ║ 23/11/2016 ║ Annual Leave ║ 
║ 67890 ║ 22/11/2016 ║ Annual Leave ║ 
║ 67890 ║ 21/11/2016 ║ Annual Leave ║ 
║ 67890 ║ 18/11/2016 ║ Work   ║ 
║ 67890 ║ 17/11/2016 ║ Work   ║ 
║ 67890 ║ 16/11/2016 ║ Work   ║ 
║ 67890 ║ 15/11/2016 ║ Sick Leave ║ 
║ 67890 ║ 14/11/2016 ║ Sick Leave ║ 
║ 67890 ║ 11/11/2016 ║ Sick Leave ║ 
║ 67890 ║ 10/11/2016 ║ Work   ║ 
║ 67890 ║ 9/11/2016 ║ Work   ║ 
║ 67890 ║ 8/11/2016 ║ Work   ║ 
║ 67890 ║ 7/11/2016 ║ Work   ║ 
║ 67890 ║ 4/11/2016 ║ Work   ║ 
║ 67890 ║ 3/11/2016 ║ Annual Leave ║ 
║ 67890 ║ 2/11/2016 ║ Annual Leave ║ 
║ 67890 ║ 1/11/2016 ║ Work   ║ 
║ 67890 ║ 31/10/2016 ║ Work   ║ 
╚══════════╩════════════╩══════════════╝ 

对于给定的员工,日期和活动,我需要从该日期向后工作,并找到最近,鉴于活动的块的起始日期。 '块'是同一活动的任何组,因此可能需要1天或多天。

作为一个例子,使用上面的表格,假设我需要找到雇员12345从20/11/2016起倒退工作的最近'病假'的开始日期。在这种情况下,我希望得到'11/11/2016'的价值,因为这是最近一次病假的开始日期。

作为另一个例子,使用上面的表格,假设我需要查找自2016年11月20日起向后工作的员工67890的最近“年假”的开始日期。在这种情况下,我希望获得'21/11/2016'的价值,因为这是最近一次年假的开始日期。

回答

1

这是“间隙和岛屿”问题的一个例子。您可以使用行号差异方法得到员工的活动期:

select employee, activity, min(date), max(date) 
from (select t.*, 
      row_number() over (partition by employee order by date) as seqnum_e, 
      row_number() over (partition by employee, activity order by date) as seqnum_ea 
     from t 
    ) t 
group by employee, activity, (seqnum_e - seqnum_ea); 

然后,您可以使用它来回答您的问题。例如:

with ea as (
     select employee, activity, min(date) as date_from, max(date) as date_to 
     from (select t.*, 
        row_number() over (partition by employee order by date) as seqnum_e, 
        row_number() over (partition by employee, activity order by date) as seqnum_ea 
      from t 
      ) t 
     group by employee, activity, (seqnum_e - seqnum_ea) 
    ) 
select top 1 ea.* 
from ea 
where employee = 12345 and activity = 'Sick Leave' 
order by date_from desc; 

对于特定问题还有其他解决方案,但这可能是最一般的问题。

+0

看起来不错,谢谢! – Goolsy

相关问题