При работе с датами и вы хотите проверить перекрывающихся интервалов, расчет немного сложнее. Предположим, что для любых двух интервалов [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. Вторая запись больше не перекрывается с первой записью - третья запись. Если это не возможно с вашими данными, просто установите его обратно.