SQL中的有效日期比较

时间:2012-11-26 14:27:47

标签: sql-server tsql sql-server-2005

我希望这个问题提供所有必要的信息,但如果有任何不清楚的地方,请提出更多要求。这是关于堆栈溢出的第一个问题所以请耐心等待。

我在SQL Server 2005上运行此查询。

我有一个大的派生数据集(我稍后会提供一个小子集),它有4个字段; ID, 年, 开始日期, 结束日期

在此数据集中,ID可能(正确地)出现多次,具有不同的日期组合。

我的问题是如何识别记录是否为“新”.I它的开始日期不会落在同一个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/2008和01/01/2009)

第4行和第5行将被视为新记录,因为它不直接附加到ID 1的上一期间的末尾或与任何其他期间重叠。

目前要获取此数据集,我必须将所有数据放入临时表中,然后将它们连接在一起,以删除我不想要的记录。

首先,我删除startdate等于该ID的另一行的enddate的行(这将删除第3行和第7行)

然后我删除开始日期在该ID的其他记录的startdate和enddate之间的行(这将删除第2行和第8行)

这会让我在第1,4,5和6行作为“新”记录是正确的。

有没有更有效的方法来执行此操作,例如在某种循环中,CTE或咳嗽光标?

如上所述,如果有任何不清楚的地方,请不要犹豫,我会尽力向您提供您要求的信息。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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