Получить даты в течение 50 дней с указанной даты - PullRequest
0 голосов
/ 05 мая 2018

Таблица активности:

create table #activity(id int, begin_date datetime, end_date datetime)
insert into #activity values(1, '1/1/2017', '1/31/2017')

insert into #activity values(1, '9/1/2017', '9/15/2017')

insert into #activity values(1, '4/1/2017', '4/15/2017')

insert into #activity values(1, '2/5/2017', '2/15/2017')

insert into #activity values(1, '8/1/2017', '8/31/2017')

Insert into #activity values(2, '11/1/2016', '11/15/2016')

Теперь дата ввода - 12/1/2016, и id, хотел бы получить все действия в течение 50 дней после 12/1/2016. Запрос должен возвращать действия с датами начала 01.01.2017, 05.02.2017 (потому что это в течение 50 дней после 31.01.2017) и 4/1/17.

8/1/2017 и 01.09.2017 с идентификатором 1 не должны быть выбраны 8/1 не с 50 дней 4/15 и 50-дневный цикл был прерван.

ТИА

1 Ответ

0 голосов
/ 06 мая 2018

ОП говорит:

хотел бы получить все действия в течение 50 дней после 12/1/2016

Один из возможных запросов для достижения этого результата будет

-- get all activities with a begin_date within 50 days of input_date
select *
from #activity as a
where @input_date <= a.begin_date and a.begin_date < dateadd(day, 50, @input_date)

Однако ФП говорит:

Запрос должен возвращать действия с датами начала 01.01.2017, 05.02.2017 (потому что это в течение 50 дней с 31.01.2017) и 01.04.17. 01.08.2017 и 01.09.2017 с идентификатором 1 не должны быть выбраны 8/1 не с 50 дней 4/15 и 50-дневный цикл был прерван.

Это будет означать, что вы хотите найти все последовательные действия, начинающиеся после 1.12.2016, где разрыв между последовательными действиями составляет менее 50 дней.

Одним из возможных подходов для этого является использование функции lag . Пример использования функции задержки в этой проблеме:

select
    a.*
    , lag(a.end_date, 1, @input_date) over (order by a.end_date) as previous_end
    , datediff(day, lag(a.end_date, 1, @input_date)  over (order by a.end_date), a.begin_date) as previous_end_to_this_begin
from #activity as a
where @input_date <= a.begin_date
order by a.begin_date

Если немного упростить, то получится:

-- get all activities in a row where the gap between activities is less than 50
select * from #activity as a where @input_date <= a.begin_date and a.begin_date < (
select
    min(a.begin_date) as first_begin_to_not_include
from
    (
        select
            a.begin_date
            , datediff(day, lag(a.end_date, 1, @input_date)  over (order by a.end_date), a.begin_date) as previous_end_to_this_begin
        from #activity as a
        where @input_date <= a.begin_date
    ) as a
where a.previous_end_to_this_begin > 50
)
order by a.begin_date
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...