如何排除周末和节假日日期并在 MySQL 中找到预期日期?
How to exclude weekends and holidays dates and find an expected date in MySQL?
我正在处理一项任务,我有 2 tables。即 tickets
和 holidays
.
现在我也有完成工单的天数了。现在我需要通过排除假期(在 holidays
table 中指定)和 weekends
.
来找到预期日期
现在我可以使用 ticket created date
和 days to complete the ticket
查找日期。但无法通过去除节假日和周末来计算预产期。
如果机票预计到期日在节假日或周末,我们需要将预计到期日提前。
然后我们需要比较 ticket_closed_date
和 expected_due_date
。
如果ticket_closed_date <= expected_due_date
则需要returnisSlaMet
为YES
。否则需要 return isSlaMet
作为 NO
.
门票Table
节假日Table
示例: 通常,如果工单是在 2nd October,2020
上创建的,并且其完成天数是 3
,那么预期的截止日期将是 5th October
我们放假了,5th October
。但是在工单创建日期和预计到期日期之间有 1 个假期和 2 个周末。即 3rd, 4th and 5th of October
。所以我们需要将预产期延长 3 days
(因为 2 个周末 + 1 个假期)。即 8th October
。票务已于 9th October
.
关闭
然后我们需要比较ticket closed date(9th october)
和expected due date(8th October)
和returnisSlaMet
作为YES
。
预期输入
Tickets Table
--------------------------------------------------------------------------------
tid createdAt apply_sla ticket_closed_date days_to_complete
--------------------------------------------------------------------------------
100 2020-10-02 00:00:00 1 2020-10-09 00:00:00 3
--------------------------------------------------------------------------------
Holidays Table
----------------------------------------------
id holiday_date end_date
----------------------------------------------
20 2020-10-05 2020-10-05
----------------------------------------------
Along with the above holiday, we need to exclude Weekends.
预期输出
Tickets Table
--------------------------------------------------------------------------------------------------------------------------
tid createdAt apply_sla ticket_closed_date days_to_complete expected_due_date completedIn isSlaMet
--------------------------------------------------------------------------------------------------------------------------
100 2020-10-02 00:00:00 1 2020-10-09 00:00:00 3 2020-10-08 00:00:00 4 NO
--------------------------------------------------------------------------------------------------------------------------
这是我到目前为止一直在使用的查询。
SELECT
`t`.`tid`, `t`.`createdAt`, `t`.`days_to_complete`,
`t`.`ticket_closed_date`,`holidays`.`holiday_date`,
`holidays`.`end_date`, `t.apply_sla`,
IF(ISNULL(`t`.`ticket_closed_date`),
NULL,
IF((`t`.`apply_sla` = 1),
IF(((CAST(`t`.`createdAt` AS DATE) + INTERVAL (`t`.`days_to_complete` + 1) DAY) BETWEEN `holidays`.`holiday_date` AND `holidays`.`end_date`),
IF((CAST(`t`.`ticket_closed_date` AS DATE) <= (`holidays`.`end_date` + INTERVAL `t`.`days_to_complete` DAY)),
'YES',
'NO'),
IF((CAST(`t`.`ticket_closed_date` AS DATE) <= (`t`.`createdAt` + INTERVAL (`t`.`days_to_complete` + 1) DAY)),
'YES',
'NO')),
IF(((TO_DAYS(`t`.`ticket_closed_date`) - TO_DAYS(`t`.`createdAt`)) > (`t`.`days_to_complete` + 1)),
'NO',
'YES')
)
) AS `isSlaMet`
FROM
(`tickets` `t`
LEFT JOIN `holidays` ON (((CAST(`t`.`createdAt` AS DATE) + INTERVAL (`t`.`days_to_complete` + 1) DAY) BETWEEN `holidays`.`holiday_date` AND `holidays`.`end_date`)))
ORDER BY `t`.`tid` DESC;
这比看起来更复杂。最简单的方法可能是暴力破解:使用递归 CTE(仅在 MySQL 8.0 中可用)枚举工单创建日期和关闭日期之间的所有天数,然后过滤掉周末和节假日以计算 SLA 天数:
with recursive cte_tickets as (
select tid, created_at as dt, ticket_closed_date
from tickets
where apply_sla = 1
union all
select tid, dt + interval 1 day, ticket_closed_date
from cte_tickets
where dt < ticket_closed_date
)
select t.*,
t.created_at
+ interval (t.days_to_complete + sum(weekday(dt) in (5, 6) or h.holiday_date is not null)) day
as expected_due_date,
count(*) - sum(weekday(dt) in (5, 6) or h.holiday_date is not null) - 1 completed_in,
t.ticket_closed_date <= t.created_at
+ interval (t.days_to_complete + sum(weekday(dt) in (5, 6) or h.holiday_date is not null)) day
as is_sla_met
from tickets t
inner join cte_tickets ct on ct.tid = t.tid
left join holidays h on ct.dt between h.holiday_date and h.end_date
group by t.tid
tid | created_At | apply_sla | ticket_closed_date | days_to_complete | expected_due_date | completed_in | is_sla_met
--: | :------------------ | :-------- | :------------------ | ---------------: | :------------------ | -----------: | ---------:
100 | 2020-10-02 00:00:00 | 1 | 2020-10-09 00:00:00 | 3 | 2020-10-08 00:00:00 | 4 | 0
我正在处理一项任务,我有 2 tables。即 tickets
和 holidays
.
现在我也有完成工单的天数了。现在我需要通过排除假期(在 holidays
table 中指定)和 weekends
.
现在我可以使用 ticket created date
和 days to complete the ticket
查找日期。但无法通过去除节假日和周末来计算预产期。
如果机票预计到期日在节假日或周末,我们需要将预计到期日提前。
然后我们需要比较 ticket_closed_date
和 expected_due_date
。
如果ticket_closed_date <= expected_due_date
则需要returnisSlaMet
为YES
。否则需要 return isSlaMet
作为 NO
.
门票Table
节假日Table
示例: 通常,如果工单是在 2nd October,2020
上创建的,并且其完成天数是 3
,那么预期的截止日期将是 5th October
我们放假了,5th October
。但是在工单创建日期和预计到期日期之间有 1 个假期和 2 个周末。即 3rd, 4th and 5th of October
。所以我们需要将预产期延长 3 days
(因为 2 个周末 + 1 个假期)。即 8th October
。票务已于 9th October
.
然后我们需要比较ticket closed date(9th october)
和expected due date(8th October)
和returnisSlaMet
作为YES
。
预期输入
Tickets Table
--------------------------------------------------------------------------------
tid createdAt apply_sla ticket_closed_date days_to_complete
--------------------------------------------------------------------------------
100 2020-10-02 00:00:00 1 2020-10-09 00:00:00 3
--------------------------------------------------------------------------------
Holidays Table
----------------------------------------------
id holiday_date end_date
----------------------------------------------
20 2020-10-05 2020-10-05
----------------------------------------------
Along with the above holiday, we need to exclude Weekends.
预期输出
Tickets Table
--------------------------------------------------------------------------------------------------------------------------
tid createdAt apply_sla ticket_closed_date days_to_complete expected_due_date completedIn isSlaMet
--------------------------------------------------------------------------------------------------------------------------
100 2020-10-02 00:00:00 1 2020-10-09 00:00:00 3 2020-10-08 00:00:00 4 NO
--------------------------------------------------------------------------------------------------------------------------
这是我到目前为止一直在使用的查询。
SELECT
`t`.`tid`, `t`.`createdAt`, `t`.`days_to_complete`,
`t`.`ticket_closed_date`,`holidays`.`holiday_date`,
`holidays`.`end_date`, `t.apply_sla`,
IF(ISNULL(`t`.`ticket_closed_date`),
NULL,
IF((`t`.`apply_sla` = 1),
IF(((CAST(`t`.`createdAt` AS DATE) + INTERVAL (`t`.`days_to_complete` + 1) DAY) BETWEEN `holidays`.`holiday_date` AND `holidays`.`end_date`),
IF((CAST(`t`.`ticket_closed_date` AS DATE) <= (`holidays`.`end_date` + INTERVAL `t`.`days_to_complete` DAY)),
'YES',
'NO'),
IF((CAST(`t`.`ticket_closed_date` AS DATE) <= (`t`.`createdAt` + INTERVAL (`t`.`days_to_complete` + 1) DAY)),
'YES',
'NO')),
IF(((TO_DAYS(`t`.`ticket_closed_date`) - TO_DAYS(`t`.`createdAt`)) > (`t`.`days_to_complete` + 1)),
'NO',
'YES')
)
) AS `isSlaMet`
FROM
(`tickets` `t`
LEFT JOIN `holidays` ON (((CAST(`t`.`createdAt` AS DATE) + INTERVAL (`t`.`days_to_complete` + 1) DAY) BETWEEN `holidays`.`holiday_date` AND `holidays`.`end_date`)))
ORDER BY `t`.`tid` DESC;
这比看起来更复杂。最简单的方法可能是暴力破解:使用递归 CTE(仅在 MySQL 8.0 中可用)枚举工单创建日期和关闭日期之间的所有天数,然后过滤掉周末和节假日以计算 SLA 天数:
with recursive cte_tickets as (
select tid, created_at as dt, ticket_closed_date
from tickets
where apply_sla = 1
union all
select tid, dt + interval 1 day, ticket_closed_date
from cte_tickets
where dt < ticket_closed_date
)
select t.*,
t.created_at
+ interval (t.days_to_complete + sum(weekday(dt) in (5, 6) or h.holiday_date is not null)) day
as expected_due_date,
count(*) - sum(weekday(dt) in (5, 6) or h.holiday_date is not null) - 1 completed_in,
t.ticket_closed_date <= t.created_at
+ interval (t.days_to_complete + sum(weekday(dt) in (5, 6) or h.holiday_date is not null)) day
as is_sla_met
from tickets t
inner join cte_tickets ct on ct.tid = t.tid
left join holidays h on ct.dt between h.holiday_date and h.end_date
group by t.tid
tid | created_At | apply_sla | ticket_closed_date | days_to_complete | expected_due_date | completed_in | is_sla_met --: | :------------------ | :-------- | :------------------ | ---------------: | :------------------ | -----------: | ---------: 100 | 2020-10-02 00:00:00 | 1 | 2020-10-09 00:00:00 | 3 | 2020-10-08 00:00:00 | 4 | 0