计算从第二天开始的日期之间的工作日

时间:2014-02-27 12:39:02

标签: mysql sql

我有一个计算两个日期之间工作日的函数。问题是它必须从开始日期后的第二天开始计算。如果开始日期是周末(周六或周日)或周五,则必须从周一开始计算。

目前,此代码会计算在周末开始的日期,但如果开始日期是在工作日,那么它会计算 1天太多因为它还会计算开始日应该从第二天开始

CREATE DEFINER=`root`@`localhost` FUNCTION `BusinessDaysBetweenDates`(d1 DATE, d2 DATE) RETURNS int(11)
BEGIN
    DECLARE bDaysInPeriod INT;

    SET bDaysInPeriod=0;
    WHILE d1<=d2 DO
        IF DAYOFWEEK(d1) BETWEEN 2 AND 6 THEN
            SET bDaysInPeriod=bDaysInPeriod+1;
        END IF;

        SET d1=d1+INTERVAL 1 day;
    END WHILE;

    RETURN bDaysInPeriod;
END

测试用例:使用开始日期 01-01-2014结束日期 03-01-2014它将生成{{1什么时候它应该产生3 days。如果您通过简单地从结果中减去1天来修复它,那么2 days开始日期04-01-2014结束日期将产生{{1而不是08-01-2014

2 个答案:

答案 0 :(得分:1)

您解决此问题的方法似乎可行。当您向应用程序添加任意假期表时,它将特别有用。

我相信你的计算中有一个简单的逐个错误。尝试更改逻辑来执行此操作:

SET bDaysInPeriod=0;
SET d1=d1+INTERVAL 1 DAY;    /* start counting the day after start date */
WHILE d1<=d2 DO
    IF DAYOFWEEK(d1) BETWEEN 2 AND 6 THEN
        SET bDaysInPeriod=bDaysInPeriod+1;
    END IF;
    SET d1=d1+INTERVAL 1 DAY;
END WHILE;
RETURN bDaysInPeriod;

以下是一些潜在的测试用例:

 start date  end date   returned value

   Mon         Tues        1
   Sun         Mon         1
   Fri         Mon         1
   Fri         Tues        2
   Sat         Sun         0
   Sat         Mon         1
   Sun         Tues        2

我认为这就是你想要的。

答案 1 :(得分:0)

在调用该函数之前,在开始日中添加一天。

如果开始日是星期五,你会得到星期六,这不会被计算在内,因为它不是工作日。如果开始日是星期天,那么你最终会在星期一结束,这将是第一天被计算在内。


或者您可以跳过该功能并在查询中执行此操作。

WITH days AS (
   SELECT TRUNC(:start_date) + LEVEL AS my_day
   FROM dual
   CONNECT BY TRUNC(:start_date) + LEVEL <= TRUNC(:end_date)
)
SELECT COUNT(*) AS workdays
FROM days
WHERE TO_CHAR(my_day, 'D') NOT IN ('1', '7');

您需要排除的天数取决于您要排除的实际天数以及您的NLS设置,确切地说是NLS_TERRITORY。在这里,我假设您想要排除周末,并设置1 =星期日和7 =星期六。