Я бы пошел с некоторым алгоритмом функции окна. тестовые данные
входа:
create table tt (key varchar(10), dte date);
insert into tt values ('w1', '2017-12-01');
insert into tt values ('w1', '2017-11-01');
insert into tt values ('w1', '2015-12-01');
insert into tt values ('w1', '2015-11-01');
insert into tt values ('w1', '2016-01-01');
insert into tt values ('w1', '2016-02-01');
insert into tt values ('w1', '2016-05-01');
insert into tt values ('w1', '2016-06-01');
insert into tt values ('w2', '2016-02-01');
insert into tt values ('w2', '2016-03-01');
insert into tt values ('w2', '2016-05-01');
insert into tt values ('w3', '2016-01-01');
insert into tt values ('w3', '2016-02-01');
Затем мы используем функцию окна, чтобы создать группу между датой для непрерывного извлечь рабочее время.
Отсюда нам просто нужно сделать счет - 1, с другой группой по выражению, чтобы иметь количество пробелов.
with tmp as (
select key,
dte,
dte - (row_number() over(partition by key order by dte) MONTHS) as rnk_month,
row_number() over(partition by key order by dte) as rnk_tot
from tt)
select key, min(dte), max(dte), rnk_month
from tmp
group by key, rnk_month
order by key, rnk_month
Пробуя запрос с помощью синтаксиса sqlServer ...(Не уверен, что он будет работать, пока я не SQLs)
with tmp as (
select key,
dte,
dateadd(month, - row_number() over(partition by key order by dte), dte) as rnk_month,
row_number() over(partition by key order by dte) as rnk_tot
from tt)
select key, min(dte), max(dte), rnk_month
from tmp
group by key, rnk_month
order by key, rnk_month
Чтобы объяснить немного больше:
Функция: row_number() над (раздел по ключевому распоряжению DTE) будет outpout это для работника 1:
-----------------------------
Worker | Month | rnk_tot
-----------------------------
w1 |2015-11-01 | 1
w1 |2015-12-01 | 2
w1 |2016-01-01 | 3
w1 |2016-02-01 | 4
w1 |2016-05-01 | 5
w1 |2016-06-01 | 6
w1 |2017-11-01 | 7
w1 |2017-12-01 | 8
Теперь, если мы вычтем дату с учетом rnk_tot rnk_tot как месяц, мы будем иметь некоторые новые даты, которые образуют некоторую непрерывную группу:
----------------------------------------
Worker | Month | rnk_tot | rnk_month
----------------------------------------
w1 |2015-11-01 | 1 |2015-10-01
w1 |2015-12-01 | 2 |2015-10-01
w1 |2016-01-01 | 3 |2015-10-01
w1 |2016-02-01 | 4 |2015-10-01
w1 |2016-05-01 | 5 |2015-12-01
w1 |2016-06-01 | 6 |2015-12-01
w1 |2017-11-01 | 7 |2017-04-01
w1 |2017-12-01 | 8 |2017-04-01
Отсюда вы можете сделать группу, на работника и rnk_month столбца Gatter непрерывного рабочего времени (это то, что запрос я отправил сделать):
----------------------------------------
Worker | Mth Min | Mth Max | rnk_month
----------------------------------------
w1 |2015-11-01 |2016-02-01|2015-10-01
w1 |2016-05-01 |2016-06-01|2015-12-01
w1 |2017-11-01 |2017-12-01|2017-04-01
И здесь вы можете иметь номер пробелов. Таким образом, окончательный запрос может быть:
with tmp as (
select key,
dateadd(month, - row_number() over(partition by key order by dte), dte) as rnk_month
from tt)
select key, count(distinct rnk_month) - 1 as gaps
from tmp
group by key
Это даст этот выход для теста я использовал:
-----------------
Worker | Gaps
-----------------
w1 | 2
w2 | 1
w3 | 0
Как вы получаете значение «1» для «worker001»? Кроме того, пометьте свой вопрос в базе данных, которую вы используете. –
Какая СУБД вы используете? –
Алгоритм должен работать при изменении года? – Nemeros