在数学上找到第五个星期六?

时间:2017-12-11 23:57:51

标签: mysql math

所以,在我工作的地方,我的员工周六交替工作:一些员工被分配到每个月的第一个和第三个星期六工作,一些员工被分配到每个月的第二个和第四个星期六工作。

出现了一个小问题:一年中有四个月有五个星期六。这很容易解决:第一/第三名员工在一年中的第一和第三个星期六工作,依此类推。

有些年份有五个月的第五个星期六,但我们现在还没有谈论这个。

无论如何,要为我的员工生成计划,我首先使用以下代码生成日期列表:

    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

然后,我从子查询中选择日期,并将它们连接到我的计划表,以创建每个员工在每个日期工作的列表。

所有这一切都很好,直到第五个星期六重新抬起他们丑陋的脑袋。目前,我使用以下代码在数学上找出一年中的第五个星期六:

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)

或者,总结一下,我发现从当前的第一个星期日到本周六的星期六已经过去的天数,将它除以7来计算自那时以来已经过了多少个星期六,然后找到4的模数来计算出多少"额外"从那以后第五个星期六过去了。

...并且此代码将完美地运行,除非第五个星期六恰好落在一个四周的倍数上。值得庆幸的是,今年并没有发生这种情况,但明年我需要弄清楚如何解决这个问题。

有没有更好的方法可以在数学上找出第五个星期六的第五个星期六?

1 个答案:

答案 0 :(得分: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;