2015-07-13 73 views
0

我需要一些幫助,因爲我沒有使用SQL語句那麼好......SQL查詢合併連續的日期,而忽略非連續的一

我在數據庫如下表:

+------+------------+------------+ 
| E_ID | FromDate | ToDate | 
+------+------------+------------+ 
| 555 | 2012-01-01 | 2012-12-31 | 
| 555 | 2013-01-01 | 2013-12-31 | 
| 555 | 2014-01-01 | 2014-04-30 | 
| 555 | 2014-05-01 | 2014-08-15 | 
| 555 | 2014-08-16 | 2014-12-31 | 
| 555 | 2015-01-01 | 2015-06-25 | 
| 555 | 2015-07-01 | 2015-12-31 | 
+------+------------+------------+ 

我要合併連續日期,由今年分組,玩一點後,我來到這個查詢:

select E_ID 
     ,FromDate = MIN(FromDate) 
     ,ToDate = MAX(ToDate) 
from TbTest 
group by E_ID 
     ,DATEPART(YEAR,FromDate) 
     ,DATEPART(YEAR,ToDate) 

而結果幾乎是我想要的東西:

+------+------------+------------+ 
| E_ID | FromDate | ToDate | 
+------+------------+------------+ 
| 555 | 2012-01-01 | 2012-12-31 | 
| 555 | 2013-01-01 | 2013-12-31 | 
| 555 | 2014-01-01 | 2014-12-31 | 
| 555 | 2015-01-01 | 2015-12-31 | 
+------+------------+------------+ 

這幾乎是完美的。這裏的問題是,在日期2015年我們有一個重疊:

| 555 | 2015-01-01 | 2015-06-25 | 
| 555 | 2015-07-01 | 2015-12-31 | 

所以不是沒有fromdate是2015年6月26日,這是2015年7月1日,所以我們有一個「缺口」 6天。對於這些特殊情況下,我想拆了他們,讓我想要的結果是這樣的:

+------+------------+-------------+ 
| E_ID | FromDate | ToDate | 
+------+------------+-------------+ 
| 555 | 2012-01-01 | 2012-12-31 | 
| 555 | 2013-01-01 | 2013-12-31 | 
| 555 | 2014-01-01 | 2014-12-31 | 
| 555 | 2015-01-01 | 2015-06-25 | 
| 555 | 2015-07-01 | 2015-12-31 | 
+------+------------+-------------+ 

在小的話,我需要真實地連續日期沒有一天失蹤合併。

PS:我現在正在考慮和todate可以像9999-12-31有時,所以我我的團隊在今年其實是不正確的......

謝謝您的幫助!

+0

如果您需要「無間隙」列表,最好只存儲「ToDate」並計算後退時間。在你的情況下,如果你不想得到一個非常緩慢和複雜的查詢,我會考慮填補與虛設期間的差距。 – Shnugo

+0

如果一次最多隻有一個重疊,那麼這更容易......是否有更多?提示,使用遞歸CTE – Hogan

+1

這可能是遊標實際上比基於集合的查詢執行得更好的罕見情況之一。 –

回答

1

對不起,因爲我沒有時間測試下面的代碼,但我認爲這個想法在這裏。

with aggr as 
(
select E_ID, 
     FromDate, 
     ToDate, 
     lev = 0 
from TbTest 
UNION ALL 
select T.E_ID, 
     A.FromDate, 
     T.ToDate, 
     lev = A.lev + 1 
from TbTest T 
     inner join aggr A 
     on T.e_ID = A.E_ID AND datediff(day,A.Todate,T.FromDate) = 1 
     AND DATEPART(YEAR,A.TODate) = DATEPART(YEAR,T.FromDate) 
) 

select E_ID, FromDate, ToDate from aggr 
EXCEPT 
Select AG1.E_ID, AG1.FromDate, AG1.ToDate 
from aggr AG1 
inner join aggr AG2 
ON AG1.E_ID = AG2.E_ID 
    AND AG1.Fromdate >= AG2.fromdate and AG1.todate <= AG2.todate and AG1.lev < AG2.lev 
Order by E_ID, Fromdate 

編輯1:我修好了腳本。這裏是SQL Fiddle

+1

不錯。要合併同一天結束和開始的項目,只需在datediff後進行更改<= 1即可。 – Hogan

+0

謝謝,那正是我需要的! – angra