我有以下示例数据:
id Ref User Task Refernce Start End rn
1 12222 Joe Bloggs Task 1 Ref001 24/02/2014 20/07/2014 1
2 12568 Joe Bloggs Task 1 Ref001 25/07/2014 12/10/2014 2
3 14757 Joe Bloggs Task 1 Ref001 29/10/2014 11/01/2015 3
4 12493 Joe Bloggs Task 1 Ref001 7/01/2015 6/04/2015 4
5 13694 Joe Bloggs Task 2 Ref001 3/04/2014 20/07/2014 1
6 85569 Joe Bloggs Task 2 Ref001 18/07/2014 12/10/2014 2
7 54769 Joe Bloggs Task 2 Ref001 24/11/2014 5/01/2015 3
8 89716 Joe Bloggs Task 2 Ref001 12/01/2015 6/04/2015 4
我需要检查任何开始/结束日期在任务类型相同的前一个开始/结束日期之间的位置。
在上述数据中,标记为重叠的行将是:
4 12493 Joe Bloggs Task 1 Ref001 7/01/2015 6/04/2015 4
因为07/01/2015
的开始日期与11/01/15
的结束日期重叠
6 85569 Joe Bloggs Task 2 Ref001 18/07/2014 12/10/2014 2
因为18/07/2014
的开始日期与20/07/14
有人可以在不使用光标的情况下告知如何实现这一目标吗?
答案 0 :(得分:5)
您可以使用SQL Server 2012+中的lag()
执行此操作。在SQL Server 2008中,我建议使用join
:
select s.*,
(case when s.start between s2.start and s2.end then 1 else 0 end) as flg
from sample s left outer join
sample sprev
on s.id = sprev.id + 1;
答案 1 :(得分:0)
使用日期并且您想要检查重叠间隔时,计算有点复杂。考虑到任何两个区间[I1,I2]的起始日期[S1,S2]和结束日期[E1,E2],下面显示了它们可以重叠的所有方式。
I1: S1|----------|E1
I2: S2|---------|E2
I1: S1|----|E1
I2: S2|---------|E2
I1: S1|----------|E1
I2: S2|---|E2
I1: S1|----------|E1
I2: S2|---------|E2
当不重叠
时,更容易显示I1: S1|-------|E1
I2: S2|-------|E2
I1: S1|-------|E1
I2: S2|-------|E2
由此我们可以导出“无重叠”的等式:
E2 <= S1 OR S2 >= E1
由于您对“是重叠”感兴趣,只需反转:
E2 > S1 and S2 < E1
或者,如果您订购了日期,那么您知道,S2会始终在S1之后,测试可以简化为
E2 > S1
基于此,这是查询:
select s1.*, s2.Ref, s2.EndDt PrevEndDt
from source s1
join source s2
on s2.Task = s1.Task
and s2.StartDt < s1.StartDt -- examine only previous dates
and s2.EndDt > s1.StartDt; -- test for overlap
这只显示重叠的间隔。
请注意,查询会忽略任务序列值rn
(和ID),而只会查看开始日期。这有几个好处:
这依赖的一个假设是存在唯一约束,以便在任务中不能有相同的开始日期。这似乎是一个明显的限制因为你不想要重叠。加上(Task,StartDt)索引是一个明智的步骤。
SQLFiddle目前似乎已经失败了。但我的测试脚本并不大。
create table Source(
ID int not null,
Ref int not null,
UserName varchar( 16 ) not null,
Task varchar( 16 ) not null,
Refernce varchar( 16 ) not null,
StartDt date not null,
EndDt date not null,
rn smallint not null,
constraint PK_Source primary key( ID ),
constraint CK_Source_StartEnd check( StartDt < EndDt)
);
insert into Source
select 1, 12222, 'Joe Bloggs', 'Task 1', 'Ref001', '2014-02-24', '2014-07-20', 1 union all
select 2, 12568, 'Joe Bloggs', 'Task 1', 'Ref001', '2014-07-25', '2014-10-12', 2 union all
select 3, 14757, 'Joe Bloggs', 'Task 1', 'Ref001', '2014-10-29', '2015-01-11', 3 union all
select 4, 12493, 'Joe Bloggs', 'Task 1', 'Ref001', '2015-01-07', '2015-04-06', 4 union all
select 5, 13694, 'Joe Bloggs', 'Task 2', 'Ref001', '2015-04-03', '2015-07-20', 1 union all
select 6, 85569, 'Joe Bloggs', 'Task 2', 'Ref001', '2015-09-24', '2015-10-12', 2 union all
select 7, 54769, 'Joe Bloggs', 'Task 2', 'Ref001', '2015-07-18', '2015-09-20', 3 union all
select 8, 89716, 'Joe Bloggs', 'Task 2', 'Ref001', '2016-01-12', '2016-04-06', 4;
create unique index UQ_Source_TaskStart on Source( Task, StartDt );
注意我稍微改变了任务2的日期。第二个条目不再与第一个条目重叠 - 第三个条目。如果您的数据不可能,请将其重新设置。