2016-11-23 48 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

相關問題