你如何从date_sub中排除周末?

时间:2015-04-16 14:26:13

标签: mysql date

我正在尝试使用date_sub减去当前日期 - 11天。我想排除周末..这是我到目前为止所做的:

DATE_SUB(now(), INTERVAL 11 day)

不确定如何排除周末......感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

这个问题是关于减去工作日的。假设周末是周六至周日,我们可以按如下方式编写解决方案:

我们知道:

  • 每整个星期都有5个工作日。
  • 因此,
    • num_of_weeks = floor(@num_working_days / 5)
    • delta_days = @num_working_days % 5

因此,第一个近似值可能是:

SET @num_working_days = 4; -- pick any integer
SET @num_days = 7 * FLOOR(@num_working_days / 5) - @num_working_days % 5;     
SELECT DATE_SUB(NOW(), INTERVAL @num_days DAY)

但是,这在以下和类似情况下不起作用:

  

如果今天Mondaynum_working_days % 5为1,则上述内容会错误地为您Sunday提供Friday

通常,如果出现以下情况,则会失败:

WEEKDAY(NOW()) - @num_working_days % 5 < 0

为了解决这个问题,只要满足这个条件,就必须减去额外的2天。

  • overflow_days = 2 * (WEEKDAY(NOW()) - @num_working_days % 5 < 0)

所以,第二个近似值是:

SET @num_working_days = 4;
SET @overflow_days = 2 * (WEEKDAY(NOW()) - @num_working_days % 5 < 0)
SET @num_days = 7 * FLOOR(@num_working_days / 5) - @num_working_days % 5;

SELECT DATE_SUB(NOW(), INTERVAL @num_days DAY)

最后,

只要now()不在week-end天,此功能就会有效。对于这种情况,您需要将上述公式中的now()替换为上一周的结束日期:

  • weekend_correction = DATE_SUB(NOW(), INTERVAL WEEKDAY(NOW()) % 5 DAY)

这会导致看起来很可怕但完全正常工作:

SET @num_working_days = 4;
SET @weekend_correction = DATE_SUB(NOW(), INTERVAL WEEKDAY(NOW()) % 5 DAY);
SET @overflow_days = 2 * (WEEKDAY(@weekend_correction) - @num_working_days % 5 < 0);
SET @num_days = 7 * FLOOR(@num_working_days / 5) - @num_working_days % 5;

SELECT DATE_SUB(@weekend_correction, INTERVAL @num_days DAY); 

现在,在制作中,我建议你在MySQL服务器上创建一个函数来封装这个逻辑,你可以在需要减去工作日的时候调用这个函数。

答案 1 :(得分:0)

SET @date = '2015.07.25';
SET @n =6;

SELECT DATE_SUB(
              @date,INTERVAL CASE 
                  WHEN DAYOFWEEK(@date)=1 THEN (@n +(FLOOR((@n-0.5)/5)+1)*2 - 1) 
                  WHEN DAYOFWEEK(@date)=2 THEN (@n +(FLOOR((@n-0.5)/5)+1)*2)
                  WHEN DAYOFWEEK(@date)=3 THEN (@n-1 +(FLOOR(((@n-1)-0.5)/5)+1)*2 + 1)
                  WHEN DAYOFWEEK(@date)=4 THEN (@n-2 +(FLOOR(((@n-2)-0.5)/5)+1)*2 + 2)
                  WHEN DAYOFWEEK(@date)=5 THEN (@n-3 +(FLOOR(((@n-3)-0.5)/5)+1)*2 + 3)
                  WHEN DAYOFWEEK(@date)=6 THEN (@n-4 +(FLOOR(((@n-4)-0.5)/5)+1)*2 + 4)
                  WHEN DAYOFWEEK(@date)=7 THEN (@n-5 +(FLOOR(((@n-5)-0.5)/5)+1)*2 + 5) 
             END DAY
);

@date是日期。你可以给任何日期。

@n是您要减去的工作日数。

这里给出的答案对我没有用,有时会在将来返回日期,或者给出星期日的结果,这不是工作日,所以我做了SELECT。 例如,如果给定的日期是星期一,并且您希望减去1个工作日,则会返回上周五的日期。在此代码中,非工作日被视为周六和周日。

它适用于任何日期和任何数量的工作日。

答案 2 :(得分:0)

这是计算方法,但只是简化代码:

SET @date = '2015.07.25';
SET @n =6;

SELECT DATE_SUB(
          @date,INTERVAL CASE
                    WHEN DAYOFWEEK(@date)=1 THEN (@n +(FLOOR((@n-0.5)/5)+1)*2 - 1)
                    WHEN DAYOFWEEK(@date)=2 THEN (@n +(FLOOR((@n-0.5)/5)+1)*2)
                    WHEN DAYOFWEEK(@date)>=3 THEN (@n-DAYOFWEEK(@date)-2 +(FLOOR(((@n-DAYOFWEEK(@date)-2)-0.5)/5)+1)*2 + DAYOFWEEK(@date)-2)
                    END DAY
);