Находим пятые субботы математически?

0

Итак, где я работаю, мои работники работают поочередно по субботам: некоторым сотрудникам назначают работать 1-й и 3-й субботы каждого месяца, некоторые из них назначаются на работу 2-го и 4-го суббот каждого месяца.

Возникает одна небольшая проблема: есть четыре месяца в году, которые имеют пять суббот. Который достаточно прост в работе: 1-й /3-й сотрудники работают в 1-й и 3-й по субботам в течение года и так далее.

У некоторых лет пять месяцев с пятыми субботами, но мы не говорим об этом прямо сейчас.

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

    select 
        curdate() - interval (a.a + (10 * b.a) + (100 * c.a)) day as Date
    from (
        select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
        cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
        cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
        ) as a

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

Все это прекрасно работает, пока пятая суббота не выйдет за их уродливые головы. На данный момент я использую следующий код, чтобы математически определить, в какую пятую субботу года он:

mod(((datediff(date_add(a.date, interval (7-dayofweek(a.date)) day),date_add(subdate(a.Date,dayofyear(a.date-1)), interval (1-dayofweek(subdate(a.Date,dayofyear(a.date-1)))) day))+1)/7),4)

Или, резюмируя, я нахожу количество дней, прошедших с текущего первого воскресенья года до текущей субботы на этой неделе, разделите его на семь, чтобы выяснить, сколько суббот прошло с тех пор, а затем найти по модулю из 4, чтобы выяснить, сколько "лишних" пятых суббот прошло с тех пор.

... и этот код будет отлично работать, если Пятая Суббота не выпадет на неделю, что кратно четырем. К счастью, этого не происходит в этом году, но в следующем году мне нужно выяснить, как с этим бороться.

Есть ли лучший способ математически выяснить, какая пятая суббота месяца в данную пятую субботу?

Теги:
math

1 ответ

0
Лучший ответ

О чувак. Я как-то переусердствовал над этим SQL. Это было довольно легко. Создайте три временных таблицы: один для хранения завершенной таблицы дат, один для хранения всех дат интереса в вашем периоде и третий стол, чтобы найти пятые субботы:

drop temporary table if exists DATES;
create temporary table DATES (AdherenceDates date, WhichSaturday int, 
WhichFifthSaturday int);
create temporary table DATES1 (AdherenceDates date, WhichSaturday int);
create temporary table DATES2 (FifthSaturdayDates date, WhichFifthSaturday 
int auto_increment, primary key (WhichFifthSaturday));
insert into DATES1 (AdherenceDates, WhichSaturday)
select
a.Date as AdherenceDates,
case
    when day(adddate(a.date,(7-dayofweek(a.date)))) <= 7
        then 1
    when day(adddate(a.date,(7-dayofweek(a.date)))) <= 14
        then 2      
    when day(adddate(a.date,(7-dayofweek(a.date)))) <= 21
        then 3
    when day(adddate(a.date,(7-dayofweek(a.date)))) <= 28
        then 4
    when day(adddate(a.date,(7-dayofweek(a.date)))) > 28
        then 5
end as WhichSaturday
from
(select 
    curdate() - interval (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a)) day 
as Date
from ( 
    select 0 as a union all select 1 union all select 2 union all select 3 
union all select 4 union all select 5 union all select 6 union all select 7 
union all select 8 union all select 9) as a
    cross join (select 0 as a union all select 1 union all select 2 union 
all select 3 union all select 4 union all select 5 union all select 6 union 
all select 7 union all select 8 union all select 9) as b
    cross join (select 0 as a union all select 1 union all select 2 union 
all select 3 union all select 4 union all select 5 union all select 6 union 
all select 7 union all select 8 union all select 9) as c
    cross join (select 0 as a union all select 1 union all select 2 union 
all select 3 union all select 4 union all select 5 union all select 6 union 
all select 7 union all select 8 union all select 9) as d
    ) as a
where dayofweek(a.Date) <> 1
and a.Date >= '2017-01-01'
order by a.Date asc
;
insert into DATES2 (FifthSaturdayDates)
select
a.Date as AdherenceDates
from
(select 
    curdate() - interval (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a)) day 
as Date
from ( 
    select 0 as a union all select 1 union all select 2 union all select 3 
union all select 4 union all select 5 union all select 6 union all select 7 
union all select 8 union all select 9) as a
    cross join (select 0 as a union all select 1 union all select 2 union 
all select 3 union all select 4 union all select 5 union all select 6 union 
all select 7 union all select 8 union all select 9) as b
    cross join (select 0 as a union all select 1 union all select 2 union 
all select 3 union all select 4 union all select 5 union all select 6 union 
all select 7 union all select 8 union all select 9) as c
    cross join (select 0 as a union all select 1 union all select 2 union 
all select 3 union all select 4 union all select 5 union all select 6 union 
all select 7 union all select 8 union all select 9) as d
    ) as a
where dayofweek(a.Date) = 7
and a.Date >= '2017-01-01'
and day(a.Date) > 28
order by a.date asc;
insert into DATES (AdherenceDates, WhichSaturday, WhichFifthSaturday)
select
DATES1.AdherenceDates,
DATES1.WhichSaturday,
DATES2.WhichFifthSaturday
from
DATES1
left join
DATES2
on DATES1.AdherenceDates = DATES2.FifthSaturdayDates;
drop temporary tables DATES1, DATES2;
select * from DATES
order by AdherenceDates asc;

Ещё вопросы

Сообщество Overcoder
Наверх
Меню