【发布时间】:2015-04-16 14:26:13
【问题描述】:
我正在尝试使用 date_sub 减去当前日期 - 11 天。我想排除周末..这是我到目前为止的:
DATE_SUB(now(), INTERVAL 11 day)
不确定如何排除周末...感谢任何帮助。
【问题讨论】:
-
也许这条评论会有所帮助:dev.mysql.com/doc/refman/5.1/en/…
我正在尝试使用 date_sub 减去当前日期 - 11 天。我想排除周末..这是我到目前为止的:
DATE_SUB(now(), INTERVAL 11 day)
不确定如何排除周末...感谢任何帮助。
【问题讨论】:
这个问题是关于减去工作日的。假设周末是周六-周日,我们可以写出如下解决方案:
我们知道:
floor(@num_working_days / 5)
@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)
但是,这不适用于以下和类似情况:
如果今天是
Monday和num_working_days % 5是1,上面将错误地给你Sunday,而它应该给你Friday。
一般情况下会失败:
WEEKDAY(NOW()) - @num_working_days % 5 < 0
为此,只要满足此条件,就必须额外减去 2 天。
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() 替换为上一周结束日期:
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 服务器上创建一个函数来封装这个逻辑,你可以在需要减去工作日时调用这个函数。
【讨论】:
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 个工作日,它将返回上星期五的日期。在此代码中,非工作日被视为周六和周日。
它应该适用于任何日期和给定的任何工作日数。
【讨论】:
这是相同的计算方法,只是简化了代码:
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
);
【讨论】: