2015-03-03 2 views
0

я следующий образец данных:Проверьте дату падает между предыдущей датой начала строки и дата окончания

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 

мне нужно проверить, где любой из дат начала/End находятся между предыдущим гп Start/Дата окончания где Задача является одним и тем же типом.

В приведенных выше данных строки, помеченные как перекрывающиеся бы:

4 12493 Joe Bloggs Task 1 Ref001 7/01/2015 6/04/2015 4 

, поскольку Дата начала 07/01/2015 перекрывается р-н 3 Конец Дата 11/01/15

6 85569 Joe Bloggs Task 2 Ref001 18/07/2014 12/10/2014 2 

потому, потому что Дата начала 18/07/2014 overlaps rn 1 Конец Дата 20/07/14

Может кто-нибудь, пожалуйста, сообщите, как это возможно без использования курсора?

ответ

5

Вы можете сделать это, используя lag() в SQL Server 2012+. В 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; 
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) и вместо этого смотрит только на начальные даты. Это имеет ряд преимуществ:

  1. это делает работу запроса, даже если есть пробелы в последовательности гп и
  2. находит все перекрытия (если таковые имеются) в предыдущих интервалах задачи не только непосредственно предшествующих один ,
  3. заказывает даты начала, что упрощает тест на перекрытие. Это не очень важно. Расчеты дешевы, и это не меняет план выполнения и не делает различимой разницы во времени выполнения.Но, эй, более простой код - это более простой код.

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

Смежные вопросы