2016-11-23 3 views
0

従業員が行っているアクティビティを格納するactivitiesというテーブルがあります。彼らは、彼らが働いているか、または彼らが様々なタイプの休暇にいるかのような簡単な情報を保存します。休暇、病気休暇、思いやりのある休暇などを含む。表には、従業員番号、活動のタイプ、活動がある日付が格納されています。 1日には1種類の活動しか起こらず、通常は働いている日に活動があります。たとえば、ある従業員が月曜日から金曜日の労働者で、年間休暇を取っている場合、従業員が通常働いている日ではないため、週末の日付は表には含まれません。以下は 類似の連続レコードの開始日を検索する

は、サンプルテーブルです:与えられた従業員、日付や活動については

 

╔══════════╦════════════╦══════════════╗ 
║ 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日または数日かかる可能性があります。

例として、上記の表を使用して、2011年20月20日の日付から後方に働く従業員12345の最新の「病気休暇」の開始日を見つける必要があるとします。このケースでは、最新の病気休暇の開始日であったため、私は'11/11/2016 'という値を得ようとしています。

別の例として、上記の表を使用して、20/11/2016の日付から後方に働く従業員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

関連する問題