2012-11-26 51 views
3

我希望這個問題提供了所有必要的信息,但如果有什麼不清楚的地方,請請求更多。這是我關於堆棧溢出的第一個問題,請耐心等待。SQL中的有效日期比較

我正在運行SQL Server上的這個查詢2005年

我有一個大的數據集導出(我將在後面提供一小部分),其中有4場; ID, 年份, 起始日期,結束日期

在該數據可以(正確地)設置的ID出現具有不同日期的組合多次。

我的問題是有哪些途徑,以確定是否記錄是「新」即是開始日期的任何其他記錄相同ID的開始和結束日期之間不落。

舉一個例子採取下面的數據集(我希望這個表出來正確的!);

 
+----+------+------------+------------+ 
| ID | Year | Start Date | End Date | 
+----+------+------------+------------+ 
| 1 | 2007 | 01/01/2007 | 10/10/2007 | 
| 1 | 2007 | 01/01/2007 | 05/04/2007 | 
| 1 | 2007 | 05/04/2007 | 08/10/2007 | 
| 1 | 2007 | 15/10/2007 | 20/10/2007 | 
| 1 | 2007 | 25/10/2007 | 01/01/2008 | 
| 2 | 2007 | 01/01/2007 | 01/01/2008 | 
| 2 | 2008 | 01/01/2008 | 15/07/2008 | 
| 2 | 2008 | 10/06/2008 | 01/01/2009 | 
+----+------+------------+------------+ 

如果我們說在2007年之前什麼都不存在,那麼第1行和第6行是當時的'新'。

行2,3,7,8是不是「新」的,因爲它們要麼加入先前記錄的末尾或重疊,以形成一個連續的日期時間(採取行6和7之間存在01沒有「破裂」/01/2008和01/01/2009)

第4行和第5行將被視爲新記錄,因爲它不會直接附加到ID 1前一個期間的末尾或與任何其他期間重疊。

目前拿到這組數據我已經把我所有的數據到臨時表中,然後加入他們一起在各個領域,除去我不想要的記錄。

首先我刪除其中的開始日期等於另一行的結束日期爲ID(這將擺脫行3和7)

然後我刪除行,其中的開始日期爲起始日期和結束日期之間的行其他記錄該ID(這將刪除行2和8)

這將使我withRows 1,4,5和6作爲「新」記錄這是正確的。

是否有更有效的方法來做到這一點,如在某種循環,CTE或咳嗽光標?

按照上面的,如果有什麼不清楚的地方請不要猶豫,問我會盡量爲您提供您所要求的信息。

+0

選擇表,然後單擊格式代碼圖標讓它保存你的間距。 –

+0

你的第6行應該是ID 1而不是ID 2? – Beth

+0

嗨Beth,沒有第6行應該是ID 2. ID可以出現多年,並且在這個例子中,第7行不會被認爲是新的,因爲它的開始日期匹配第6行的結束日期,即使這在先前一年 –

回答

1

嘗試

;with cte as 
(
    Select *, row_number() over (partition by id order by startdate) rn from yourtable 
) 
select distinct t1.* 
from cte t1 
    left join cte t2 
    on t1.ID = t2.ID 
    and t1.EndDate>=t2.StartDate and t1.StartDate<=t2.EndDate 
    and t1.rn<>t2.rn 
where t2.ID is null 
or t1.rn=1 
+0

Podiluska,非常感謝您的迴應。我將不得不查找你使用分區的用法(我以前沒有用過),並且在我對我的大型數據集進行測試後再回到你身邊。 如果我有任何問題了解這是如何工作的,我已經完成了 –

+0

@NeilRutland它有兩個目的在上面 - 首先找到起始條目,其次找到一個記錄ID組。 – podiluska

0

這應該工作,如果掌握各行的唯一標識符:

select * from 
tbl t3 
left outer join 
(
select distinct t1.id as id_inside, t1.recno as recno_inside 
from 
tbl t1 inner join 
tbl t2 on 
t1.id = t2.id and 
(t1.startdate <> t2.startdate or t1.enddate <> t2.enddate) and 
(t1.startdate >= t2.startdate and t1.enddate <= t2.enddate) 
) t4 on 
t3.id = t4.id_inside and 
t3.recno = t4.recno_inside 
where 
id_inside is null and 
recno_inside is null 

sqlfiddle