SQL 服务器创建班次安排 4 年 4 休,假期 4 班
SQL Server Create Shift Schedule 4 on 4 off for year with holidays for 4 shifts
我需要制定一个轮班时间表,它每年都需要完成,所以我想编写它。
我有 4 个班次,每个班次都有自己的开始停止时间(通常是相同的模式)
像 A / B 是早上 8 点到晚上 8 点(4 天)然后 C / D 晚上 8 点到早上 8 点(4 天)
班次交替 A/B 4 天,然后 C / D 4 天。
我知道有人这样做了,但我需要帮助才能知道如何或从哪里开始使用代码。
我知道我需要一个 table 的班次及其开始和停止时间,一个 table 的假期(也许 - 我认为可能有一些内置的东西可以做到这一点)。
然后我需要时间表的实际 table .. 班次、开始、停止、Day/Night、假期。
工作 4 天,休息 4 天 - 如果我提供 12 月 28 日的开始日期,则按月提供一年的完整时间表。
我怎样才能做到这一点?
我发现这个 gem 可以日复一日地进行年度化,我想我需要查找一些数学知识才能让它迭代 4 on 4 off 并且可能加入两个 table s
我不知道这是否适合您使用。尽管如此,这里有一个脚本可以在跳过假期列表的同时生成轮班列表。虽然内置了大量假设,但适应类似模式应该不会非常困难:
with const as (
select cast('20211228' as date) as basedate, 8 as cycle_length
), holidays as (
select holiday
from const cross apply (values
(datefromparts(year(basedate) + 1, 2, 14)),
(datefromparts(year(basedate) + 1, 3, 17)),
(datefromparts(year(basedate) + 1, 7, 4)),
(datefromparts(year(basedate) + 1, 10, 31))
) as h(holiday)
), numbers as (
select n
from (values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9)) as n(n)
), cycles as (
select cycle.n + (n0.n + 10 * n1.n) * cycle_length as daynum
from numbers n0 cross join numbers n1 cross join numbers cycle cross join const
where cycle.n < cycle_length and cycle.n + (n0.n + 10 * n1.n) * cycle_length < 367
)
select schedule_date, description
from const cross apply cycles cross apply
(select dateadd(day, daynum, basedate) as dt) d cross apply
(select count(*) from holidays where holiday <= dt) h(skips) cross apply
(select n from numbers where n in (1, 2)) s(shift) cross apply
(values (
dateadd(day, skips, dt),
case daynum / (cycle_length / 2) % 2
when 0 then case shift when 1 then 'A 8am-8pm' else 'B 8pm-8am' end
when 1 then case shift when 1 then 'C 8am-8pm' else 'D 8pm-8am' end
end
)) v2(schedule_date, description)
order by schedule_date;
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=1d03e27163bd37484d2d5c288eb9e80c
我需要制定一个轮班时间表,它每年都需要完成,所以我想编写它。
我有 4 个班次,每个班次都有自己的开始停止时间(通常是相同的模式) 像 A / B 是早上 8 点到晚上 8 点(4 天)然后 C / D 晚上 8 点到早上 8 点(4 天) 班次交替 A/B 4 天,然后 C / D 4 天。
我知道有人这样做了,但我需要帮助才能知道如何或从哪里开始使用代码。 我知道我需要一个 table 的班次及其开始和停止时间,一个 table 的假期(也许 - 我认为可能有一些内置的东西可以做到这一点)。
然后我需要时间表的实际 table .. 班次、开始、停止、Day/Night、假期。 工作 4 天,休息 4 天 - 如果我提供 12 月 28 日的开始日期,则按月提供一年的完整时间表。
我怎样才能做到这一点?
我发现这个 gem 可以日复一日地进行年度化,我想我需要查找一些数学知识才能让它迭代 4 on 4 off 并且可能加入两个 table s
我不知道这是否适合您使用。尽管如此,这里有一个脚本可以在跳过假期列表的同时生成轮班列表。虽然内置了大量假设,但适应类似模式应该不会非常困难:
with const as (
select cast('20211228' as date) as basedate, 8 as cycle_length
), holidays as (
select holiday
from const cross apply (values
(datefromparts(year(basedate) + 1, 2, 14)),
(datefromparts(year(basedate) + 1, 3, 17)),
(datefromparts(year(basedate) + 1, 7, 4)),
(datefromparts(year(basedate) + 1, 10, 31))
) as h(holiday)
), numbers as (
select n
from (values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9)) as n(n)
), cycles as (
select cycle.n + (n0.n + 10 * n1.n) * cycle_length as daynum
from numbers n0 cross join numbers n1 cross join numbers cycle cross join const
where cycle.n < cycle_length and cycle.n + (n0.n + 10 * n1.n) * cycle_length < 367
)
select schedule_date, description
from const cross apply cycles cross apply
(select dateadd(day, daynum, basedate) as dt) d cross apply
(select count(*) from holidays where holiday <= dt) h(skips) cross apply
(select n from numbers where n in (1, 2)) s(shift) cross apply
(values (
dateadd(day, skips, dt),
case daynum / (cycle_length / 2) % 2
when 0 then case shift when 1 then 'A 8am-8pm' else 'B 8pm-8am' end
when 1 then case shift when 1 then 'C 8am-8pm' else 'D 8pm-8am' end
end
)) v2(schedule_date, description)
order by schedule_date;
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=1d03e27163bd37484d2d5c288eb9e80c