10

SQL Server 2008 R2 を使用して、

ある終了日が次の開始日の隣にあることを考慮して、日付範囲を最大の日付範囲に結合しようとしています。

データはさまざまな雇用に関するものです。一部の従業員は、雇用を終了し、後で再入社した可能性があります。これらは 2 つの異なる雇用としてカウントする必要があります (例 ID 5)。一部の人々は、さまざまなタイプの雇用を持ち、互いに続いています (終了日と開始日が連続しています)。この場合は、合計で 1 つの雇用と見なす必要があります (例 ID 30)。

終了していない雇用期間の終了日は null です。

いくつかの例はおそらく啓発的です:

declare @t as table  (employmentid int, startdate datetime, enddate datetime)

insert into @t values
(5, '2007-12-03', '2011-08-26'),
(5, '2013-05-02', null),
(30, '2006-10-02', '2011-01-16'),
(30, '2011-01-17', '2012-08-12'),
(30, '2012-08-13', null),
(66, '2007-09-24', null)

-- expected outcome
EmploymentId StartDate   EndDate
5            2007-12-03  2011-08-26
5            2013-05-02  NULL
30           2006-10-02  NULL
66           2007-09-24  NULL

私はさまざまな「島とギャップ」の手法を試してきましたが、これを解読することはできませんでした.

4

4 に答える 4

16

日付「31211231」の使用で見られる奇妙なビットは、「終了日なし」のシナリオを処理するための非常に大きな日付です。employee ごとに実際には多くの日付範囲がないと想定しているため、単純な再帰的共通テーブル式を使用して範囲を結合しました。

実行を高速化するために、開始アンカー クエリは、前の範囲 (従業員ごと) にリンクしない日付のみを保持します。残りは、日付範囲をツリー ウォークし、範囲を拡大するだけです。最後の GROUP BY は、開始時の AN​​CHOR (employmentid、startdate) の組み合わせごとに構築された最大の日付範囲のみを保持します。


SQL フィドル

MS SQL Server 2008 スキーマのセットアップ:

create table Tbl (
  employmentid int,
  startdate datetime,
  enddate datetime);

insert Tbl values
(5, '2007-12-03', '2011-08-26'),
(5, '2013-05-02', null),
(30, '2006-10-02', '2011-01-16'),
(30, '2011-01-17', '2012-08-12'),
(30, '2012-08-13', null),
(66, '2007-09-24', null);

/*
-- expected outcome
EmploymentId StartDate   EndDate
5            2007-12-03  2011-08-26
5            2013-05-02  NULL
30           2006-10-02  NULL
66           2007-09-24  NULL
*/

クエリ 1 :

;with cte as (
   select a.employmentid, a.startdate, a.enddate
     from Tbl a
left join Tbl b on a.employmentid=b.employmentid and a.startdate-1=b.enddate
    where b.employmentid is null
    union all
   select a.employmentid, a.startdate, b.enddate
     from cte a
     join Tbl b on a.employmentid=b.employmentid and b.startdate-1=a.enddate
)
   select employmentid,
          startdate,
          nullif(max(isnull(enddate,'32121231')),'32121231') enddate
     from cte
 group by employmentid, startdate
 order by employmentid

結果

| EMPLOYMENTID |                        STARTDATE |                       ENDDATE |
-----------------------------------------------------------------------------------
|            5 |  December, 03 2007 00:00:00+0000 | August, 26 2011 00:00:00+0000 |
|            5 |       May, 02 2013 00:00:00+0000 |                        (null) |
|           30 |   October, 02 2006 00:00:00+0000 |                        (null) |
|           66 | September, 24 2007 00:00:00+0000 |                        (null) |
于 2013-04-03T09:32:42.487 に答える