2017-06-07 14 views
1

I次のデータセットがあります。ここにSQL Serverの - 見つける不在日の出現箇所

が入力画像の説明ここで

は、このデータのためのスクリプトです:

;データセットとAS( 選択 'EMP01' AS EMP_ID、CAST( '2018-01-01' AS DATE)AS PERIOD_START、CAST( '2018-01-31' AS日付)AS PERIOD_END、CAST('2018-01-07 '日付)AS CUT_DATE UNION select 'EMP01' AS EMP_ID、CAST( '2018-01-01' AS DATE)AS PERIOD_START、CAST( '2018-01-31' AS DATE)AS PERIOD_END、CAST( '2018-01-15' AS日付)AS CUT_DATE UNION 「EMP02」AS EMP_ID、CAST( '2018-01-01' AS日付)AS PERIOD_START、CAST( '2018-01-31' AS日付)AS PERIOD_END、CAST( '2018-01-09' AS (PERIOD_STARTとPERIOD_END)をCUT_DATEで除算する必要があります(その期間のカット日を除外します)。カット日数は任意です(3,5,8など) 。

上記のデータセットの結果は、次のとおりです。

+0

だから、あなたは何を試してみましたか?どこが間違っていますか? –

+0

Googleでかなりうまくカバーしています... https://stackoverflow.com/questions/20402089/detect-consecutive-dates-ranges-using-sql – Simon

+2

これは「ギャップと島」の問題として知られています。そのキーワードの下にいくつかの解決策があります。 – Stavr00

答えて

0

LAG関数を使用します。 何かを注文した場合、LAG関数は前の値を返します。

完全な説明を見つけることができます:http://www.sqlservercentral.com/articles/T-SQL/106783/

SQL ServerのバージョンがLAGをサポートしている場合、あなたはこれを使用することができ、完全なクエリ

+0

LAGはSQL 2012以降です。我々はOPのSQL版が何であるか分からない。 –

+0

ありがとう、realbart。 –

+0

@realbart ..あなたの答えを厳密に鉱山に変更する点はありません。 –

2

ためVKPの答えを見てみましょう。

SELECT EMPLOYEE_ID, 
     ITEM_TYPE, 
     MIN(APPLY_DATE) AS STARTDATE, 
     MAX(APPLY_DATE) AS ENDDATE 
FROM 
(SELECT T.*, 
     SUM(CASE WHEN PREV_TYPE=ITEM_TYPE THEN 0 ELSE 1 END) 
     OVER(PARTITION BY EMPLOYEE_ID ORDER BY APPLY_DATE) AS GRP 
    FROM (SELECT D.*, 
     LAG(ITEM_TYPE) OVER(PARTITION BY EMPLOYEE_ID ORDER BY APPLY_DATE) AS PREV_TYPE 
     FROM DATA D 
     ) T 
) T 
WHERE ITEM_TYPE IN ('Sickness','Vacation') 
GROUP BY EMPLOYEE_ID,ITEM_TYPE,GRP 

ロジックは、(apply_dateの昇順に基づいて)前の行のITEM_TYPEを取得し、現在の行の値とを比較することです。それらが等しい場合、それらは同じグループに属します。そうでなければ、あなたは新しいグループを始めます。これはウィンドウ関数sumで行われます。グループが割り当てられたら、employee_id、item_typeの日付をmaxminにするだけです。

Sample Demo

+0

こんにちはvkp、多くのお時間をありがとう。現在、私はSQL Server 2008 R2で作業中ですが、すぐに新しいバージョンを取得します。したがって、あなたのコードは参考になります。期待される結果が得られますか?残念ながら、あなたのコードが正しく動作しているかどうかを確認することはできません。 –

+0

...デモを確認してください。 –

+0

素晴らしい仕事、vkp!素敵な一日を過ごしてください:) –

0

lagがサポートされている場合、これは別の方法の方法の場合です。

Rextester Sample

with tbl as 
(select d.* 
    ,case when (item_type = lag(item_type) over (partition by employee_id order by apply_date)) 
      then 0 
      else 1 
    end grp_tmp 
from DATA2 d 
where 
    item_type <> 'Worked' 
) 
,tbl2 as 
(select t.* 
    ,sum(grp_tmp) over (order by employee_id,apply_date 
         rows between unbounded preceding and current row 
         ) 
    as grp 
from tbl t 
) 
select 
EMPLOYEE_ID 
    ,ITEM_TYPE 
    ,(CONVERT(VARCHAR(24),min(apply_date),103) 
    +' - ' 
    +CONVERT(VARCHAR(24),max(apply_date),103) 
    ) as range 
from tbl2 
group by EMPLOYEE_ID, 
     ITEM_TYPE 
     ,grp 
order by 
    employee_id 
    ,min(apply_date); 

出力

+-------------+-----------+-------------------------+ 
| EMPLOYEE_ID | ITEM_TYPE |   range   | 
+-------------+-----------+-------------------------+ 
|   1 | Sickness | 23/05/2017 - 24/05/2017 | 
|   1 | Vacation | 26/05/2017 - 29/05/2017 | 
|   1 | Sickness | 01/06/2017 - 01/06/2017 | 
|   2 | Sickness | 25/05/2017 - 30/05/2017 | 
+-------------+-----------+-------------------------+ 
+0

多くのありがとう、Utsav! –

関連する問題