mysql - 如何在 MySQL 中排除周末和节假日日期并查找预期日期?

标签 mysql sql datetime count recursive-query

我正在执行一项任务,其中有 2 个表。即ticketsholidays .

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

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

如果机票预计到期日恰逢节假日或周末,我们需要提前调整预计到期日。

之后我们需要比较ticket_closed_dateexpected_due_date .

如果ticket_closed_date <= expected_due_date然后需要返回isSlaMetYES 。否则需要返回isSlaMetNO .

门票表

enter image description here

假期表

enter image description here

示例:通常,如果工单是在 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)并返回isSlaMetYES .

预期输入

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

<强> Demo on DB Fiddle :

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

关于mysql - 如何在 MySQL 中排除周末和节假日日期并查找预期日期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64230578/

相关文章:

java - JPA 通过查询连接表

c# - 从 C# 中选择 SQL Server 数据库中的特定记录

python - 使用 pandas.to_datetime 时只保留日期部分

mysql - 如何在 MySQL 中进行连接,其中键是 key2 的子字符串?

php - PDO 中的 Mysql 变量和多个查询。更新查询不起作用

javascript - jQuery/JavaScript - 重复计时器,在达到零时保存到 MySQL

scala - 如何在 slick 3.0 的过滤器上比较 column[option[DateTime] 与 DateTime.now

mysql - 连接 MySQL 与 Visual Studio C#

php - PDO - 连接到多个数据库

datetime - MMdd 格式的 TeamCity 当前日期变量