合并连续的日期范围

Jon*_*oln 7 sql t-sql sql-server-2008-r2

使用SQL Server 2008 R2,

我正在尝试将日期范围组合到最大日期范围,因为一个结束日期与下一个开始日期相邻.

数据是关于不同的工作.一些员工可能已经结束了他们的工作,并在以后重新加入.那些应该算作两种不同的工作(例如ID 5).有些人有不同类型的工作,彼此追逐(结束和开始时间),在这种情况下,它应被视为一个就业(例如ID 30).

尚未结束的就业期限为无效的终止日期.

一些例子可能具有启发性:

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
Run Code Online (Sandbox Code Playgroud)

我一直在尝试不同的"孤岛"技术,但未能破解这一技术.

Ric*_*iwi 12

你使用日期'31211231'看到的奇怪的一点只是处理你的"无结束日期"场景的一个非常大的日期.我假设你每个员工不会有很多日期范围,所以我使用了一个简单的递归公用表表达式来组合范围.

为了使其运行更快,起始锚点查询仅保留那些不会链接到先前范围(每个员工)的日期.其余的只是树木行走的日期范围和增长范围.最终GROUP BY仅保留每个起始ANCHOR(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
*/
Run Code Online (Sandbox Code Playgroud)

查询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
Run Code Online (Sandbox Code Playgroud)

结果:

| 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) |
Run Code Online (Sandbox Code Playgroud)