【问题标题】:How to exclude weekends and holidays dates and find an expected date in MySQL?如何排除周末和节假日日期并在 MySQL 中查找预期日期?
【发布时间】:2020-10-06 17:03:56
【问题描述】:

我正在处理我有 2 张桌子的任务。即ticketsholidays

现在我也有完成门票的天数。现在我需要通过排除假期(在holidays 表中指定)和weekends 来查找预期日期。

现在我可以使用ticket created datedays to complete the ticket 查找日期。但无法通过移除节假日和周末来计算预计到期日。

如果机票预计到期日在节假日或周末,我们需要将预计到期日提前。

然后我们需要比较ticket_closed_dateexpected_due_date

如果ticket_closed_date <= expected_due_date 则需要将isSlaMet 作为YES 返回。否则需要将isSlaMet 作为NO 返回。

票务表

假期表

示例: 通常,如果在 2nd October,2020 创建工单并且完成天数是 3,那么预计到期日将是 5th October,我们有一个假期,@ 987654342@。但是在工单创建日期和预计到期日期之间有 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),并将isSlaMet作为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;

【问题讨论】:

  • 图片中的样本数据没有用。替换为 CREATE TABLE + INSERT INTO 脚本。并为提供的样本数据显示所需的输出。
  • 我只能再次向您推荐我原来的评论
  • 我已添加示例数据 我告诉您示例数据必须是 CREATE TABLE 和 INSERT INTO 脚本的组合。现在看看提供的“预期输入”......
  • 假期表中有周末吗?这将大大简化问题。

标签: mysql sql datetime count recursive-query


【解决方案1】:

这看起来更复杂。最简单的方法可能是蛮力:使用递归 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

Demo on DB Fiddle

时间 | created_At | apply_sla |门票关闭日期 | days_to_complete |预计到期日 |完成_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

【讨论】:

  • 嗨@GMB,如果有多个周末,如何在sum(weekday(dt) in (5, 6) 处理周末?我的意思是没有固定的周末。如果要完成的天数是 15 天,则中间会有多个周末。那么如何动态处理呢?
  • 感谢@GMB,一切正常。但我有一个小小的疑问。我在演示代码中添加了一张新票和假期。所有其他记录都是正确的,但是当我添加 3 天的假期时,结果 ```expected_closed_date```` 显示少了 1 天。
  • 嗨@GMB,我们没有使用 MySQL 8 或更高版本。现在它不工作了。在 8.0 版本之前如何解决这个问题?希望你能理解。
  • @Aravind:在 MySQL 5.x 中解决此类问题将具有挑战性。我建议升级...
  • @Aravind:是的,你可以......你知道你可以在你的数据库中自己测试这个,或者在我提供的小提琴中,对吧?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-03
  • 1970-01-01
  • 2023-02-08
  • 1970-01-01
  • 2015-12-29
相关资源
最近更新 更多