2017-09-29 4 views
-2

私は、次のデータセットを持っている:マージ不在期間

;with Data AS 
(
select '001' AS PERSONNUM,'2017-09-18 00:00:00.000' AS START,'2017-09-21 00:00:00.000' AS [END] 
UNION 
select '001','2017-09-22 00:00:00.000' AS START,'2017-09-22 00:00:00.000' AS [END] 
UNION 
select '002','2017-09-18 00:00:00.000' AS START,'2017-09-20 00:00:00.000' AS [END] 
UNION 
select '002','2017-09-22 00:00:00.000' AS START,'2017-09-22 00:00:00.000' AS [END] 
) 
select * from Data 
私はレコードをマージする必要が

enter image description here

場合、一部の従業員のための前の列から次の行とENDのコラムからSTART欄間の日数の差( PERSONNUM)は1に等しい。私の例では、人物 '001'のレコードは、人物 '002'のためにマージする必要があります。

だから、期待される結果は次のようになります。

enter image description here

は、事前にありがとうございます!

+1

可能な複製から直接取得これらの線に沿って何か.../question/15783315/combined-continuously-date-ranges) –

+0

@TabAlleman - 同じ問題ですが、答えとしてマークされているものよりも優れた、より効率的な解決策があります。これは始めるのが良い場所です... http://sqlmag.com/sql-server/new-solution-packing-intervals-problem –

+0

@ JasonA.Longもしあなたが望むのであれば、精巧な答えを作成することをお勧めしますリンクされた質問のそれについて!この質問は本当に重複しているように見えるので、おそらく1つに閉じられるでしょう。皆さんの洞察は誰にとっても面白いですが、彼らの洞察はもう一つの問題です。 – Pac0

答えて

2

基本的には[連続した日付の範囲を集約](https://stackoverflow.comのItzik Ben-Gan's New Solution to the Packing Intervals Problem

IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL 
DROP TABLE #TestData; 

CREATE TABLE #TestData (
    PersonId CHAR(3), 
    BegDT DATETIME, 
    EndDT DATETIME 
    ); 
INSERT #TestData(PersonId, BegDT, EndDT) VALUES 
    (1, '20151231 08:00:00', '20151231 08:30:00'), 
    (1, '20151231 08:30:00', '20151231 09:00:00'), 
    (1, '20151231 09:00:00', '20151231 09:30:00'), 
    (1, '20151231 10:00:00', '20151231 11:00:00'), 
    (1, '20151231 10:30:00', '20151231 12:00:00'), 
    (1, '20151231 11:30:00', '20151231 12:30:00'), 
    (2, '20151231 08:00:00', '20151231 10:30:00'), 
    (2, '20151231 08:30:00', '20151231 10:00:00'), 
    (2, '20151231 09:00:00', '20151231 09:30:00'), 
    (2, '20151231 11:00:00', '20151231 11:30:00'), 
    (2, '20151231 11:32:00', '20151231 12:00:00'), 
    (2, '20151231 12:04:00', '20151231 12:30:00'), 
    (3, '20151231 08:00:00', '20151231 09:00:00'), 
    (3, '20151231 08:00:00', '20151231 08:30:00'), 
    (3, '20151231 08:30:00', '20151231 09:00:00'), 
    (3, '20151231 09:30:00', '20151231 09:30:00'); 

WITH 
    cte_MPE AS (
     SELECT 
      td.PersonId, td.BegDT, td.EndDT, 
      MaxPrevEnd = MAX(td.EndDT) OVER (PARTITION BY td.PersonId ORDER BY td.BegDT, td.EndDT ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) 
     FROM 
      #TestData td 
     ), 
    cte_DivGroup AS (
     SELECT 
      m.PersonId, m.BegDT, m.EndDT, m.MaxPrevEnd, 
      DivGroup = SUM(x.NewBeg) OVER (PARTITION BY m.PersonId ORDER BY m.BegDT, m.EndDT ROWS UNBOUNDED PRECEDING) 
     FROM 
      cte_MPE m 
      CROSS APPLY (VALUES (IIF(m.BegDT <= m.MaxPrevEnd, NULL, 1))) x (NewBeg) 
     ) 
SELECT 
    dg.PersonId, 
    BegDT = MIN(dg.BegDT), 
    EndDT = MAX(dg.EndDT) 
FROM 
    cte_DivGroup dg 
GROUP BY 
    dg.PersonId, 
    dg.DivGroup 
ORDER BY 
    dg.PersonId; 

結果...

PersonId BegDT     EndDT 
-------- ----------------------- ----------------------- 
1  2015-12-31 08:00:00.000 2015-12-31 09:30:00.000 
1  2015-12-31 10:00:00.000 2015-12-31 12:30:00.000 
2  2015-12-31 08:00:00.000 2015-12-31 10:30:00.000 
2  2015-12-31 11:00:00.000 2015-12-31 11:30:00.000 
2  2015-12-31 11:32:00.000 2015-12-31 12:00:00.000 
2  2015-12-31 12:04:00.000 2015-12-31 12:30:00.000 
3  2015-12-31 08:00:00.000 2015-12-31 09:00:00.000 
3  2015-12-31 09:30:00.000 2015-12-31 09:30:00.000 
+0

ありがとう、ジェイソン。上記のアプローチを若干変更して、正しい結果を得ました。 –

+0

ようこそ。喜んで助けてください。 ;) –

+1

ありがとうございます。良い一日を :) –