2013-04-03 123 views
2

使用SQL Server 2008 R2,結合連續日期範圍

我試圖日期範圍組合成給出的最大日期範圍是一個結束日期旁邊以下的開始日期。

該數據是關於不同的就業。一些員工可能已經結束了工作,並在晚些時候重新加入。這些應該算作兩種不同的僱用(例如ID 5)。有些人有不同類型的就業機會,一個接一個地工作(結束日期和開始日期),在這種情況下,它應該被視爲總共一個就業機會(例如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 

我一直在嘗試不同的「孤島和隙」技術,但一直沒能破解這一個。

+0

不應'startDate == endDate'爲適當的重疊?否則將有24小時不明。 – MaxH

+0

這將是存儲過程,是嗎?或通過查詢限制? – orrollo

+0

@MaxH:實際上,日期時間用作日期。所以重疊是可以的。 –

回答

6

您在使用日期'31211231'時看到的奇怪位是處理您的「無結束日期」情景的非常大的日期。我假設你不會有許多日期範圍,每個員工,所以我用一個簡單的遞歸公用表表達式來結合範圍。

爲了使運行速度更快,起始錨點查詢只保留那些將而不是鏈接到之前範圍(每名員工)的日期。剩下的只是樹木漫步日期範圍和增加範圍。最後的GROUP BY只保留每個啓動ANCHOR(employmentid,startdate)組合的最大日期範圍。


SQL Fiddle

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 

Results

| 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) | 
+0

優秀!好的解決方案 –

0

用於組合所有重疊週期的修改腳本。
例如
01.01.2001-01.01.2010
05.05.2005-05.05.2015

會給一個週期:
01.01.2001-05.05.2015

tbl.enddate必須完成

;WITH cte 
    AS(
SELECT 
    a.employmentid 
    ,a.startdate 
    ,a.enddate 
from tbl a 
left join tbl c on a.employmentid=c.employmentid 
    and a.startdate > c.startdate 
    and a.startdate <= dateadd(day, 1, c.enddate) 
WHERE c.employmentid IS NULL 

UNION all 

SELECT 
    a.employmentid 
    ,a.startdate 
    ,a.enddate 
from cte a 
inner join tbl c on a.startdate=c.startdate 
    and (c.startdate = dateadd(day, 1, a.enddate) or (c.enddate > a.enddate and c.startdate <= a.enddate)) 
) 
select distinct employmentid, 
      startdate, 
      nullif(max(enddate),'31.12.2099') enddate 
from cte 
group by employmentid, startdate