2012-11-26 53 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