简体   繁体   English

从忽略周末的日期中减去天数

[英]Subtract days from a date ignoring weekend days

I'm trying to do a subtract operation on some dates, on my particular case I need to subtract only business days (excluding the weekends days, ie, Sunday and Saturday)我正在尝试在某些日期进行减法运算,在我的特定情况下,我只需要减去工作日(不包括周末,即周日和周六)

my table looks like this:我的桌子看起来像这样:

date         | days_to_subtract   | dayName
23-04-2004   |   3                | Friday
23-05-2004   |   5                | Monday
21-04-2004   |   7                | Tuesday
25-04-2004   |   30               | Monday
01-04-2004   |   22               | Thursday

My goal consist on calculate a new column (new date) by subtracting days_to_sub from date taking into account only business (laboral) days and excluding (or ignoring) the weekends days.我的目标包括通过从日期中减去days_to_sub来计算一个新列(新日期),只考虑工作日(劳动)天并排除(或忽略)周末天。

I have tried something like this:我试过这样的事情:

SELECT 
    CASE WHEN dayName = "Monday" then date_sub(date, days_to_subtract + 2)
         WHEN dayName = "Tuesday" then date_sub(date, days_to_subtract + 1)
         ELSE date_sub(date, days_to_subtract)
    END AS newColumn
FROM
    "MyTable"

But this will not work when the number of subtract days is greater than 5.但是当减去天数大于 5 时,这将不起作用。

Any suggestion using simple SQL and no complicated functions to approach a solution to this problem?任何建议使用简单的 SQL 而没有复杂的函数来解决这个问题?

Lets start with an explanation of your situation:让我们先解释一下您的情况:

Monday) Suposse we are positioned on Monday, then the result you expect to (real) subtract when substracting N (virtual) days will be like:星期一)假设我们定位在星期一,那么在减去 N(虚拟)天时您期望(真实)减去的结果将如下所示:

"Mon" - 1 day  => "Mon" - (1 + 2 * (1)) days => "Mon" - 3 days  /* 1 weekend affecting */
"Mon" - 2 days => "Mon" - (2 + 2 * (1)) days => "Mon" - 4 days  /* 1 weekend affecting */
"Mon" - 3 days => "Mon" - (3 + 2 * (1)) days => "Mon" - 5 days  /* 1 weekend affecting */
...
"Mon" - 6 days => "Mon" - (6 + 2 * (2)) days => "Mon" - 10 days /* 2 weekends affecting */
...

Tuesday) Suposse we are positioned on Tuesday, then the result you expect to (real) subtract when substracting N (virtual) days will be like:星期二)假设我们定位在星期二,那么当减去 N(虚拟)天时,您期望(真实)减去的结果将如下所示:

"Tue" - 1 day  => "Tue" - (1 + 2 * (0)) days => "Tue" - 1 days  /* 0 weekends affecting */
"Tue" - 2 days => "Tue" - (2 + 2 * (1)) days => "Tue" - 4 days  /* 1 weekend affecting */
"Tue" - 3 days => "Tue" - (3 + 2 * (1)) days => "Tue" - 5 days  /* 1 weekend affecting */
...
"Tue" - 6 days => "Tue" - (6 + 2 * (1)) days => "Tue" - 8 days  /* 1 weekend affecting */
"Tue" - 7 days => "Tue" - (7 + 2 * (2)) days => "Tue" - 11 days /* 2 weekends affecting */
...

Wednesday) Suposse we are positioned on Wednesday, then the result you expect to (real) subtract when substracting N (virtual) days will be like:星期三)假设我们定位在星期三,那么在减去 N(虚拟)天时您期望(真实)减去的结果将如下所示:

"Wed" - 1 day  => "Wed" - (1 + 2 * (0)) days => "Wed" - 1 days  /* 0 weekends affecting */
"Wed" - 2 days => "Wed" - (2 + 2 * (0)) days => "Wed" - 2 days  /* 0 weekends affecting */
"Wed" - 3 days => "Wed" - (3 + 2 * (1)) days => "Wed" - 5 days  /* 1 weekend affecting */
...
"Wed" - 6 days => "Wed" - (6 + 2 * (1)) days => "Wed" - 7 days  /* 1 weekend affecting */
"Wed" - 7 days => "Wed" - (7 + 2 * (1)) days => "Wed" - 9 days  /* 1 weekend affecting */
"Wed" - 8 days => "Wed" - (8 + 2 * (2)) days => "Wed" - 12 days /* 2 weekends affecting */
...

As we can note, there is a mathematical calculus in the middle of this logic.正如我们所注意到的,在这个逻辑的中间有一个数学演算。 If we indexes the days of the week in this way:如果我们以这种方式索引一周中的几天:

0 <-> Monday
1 <-> Tuesday
2 <-> Wednesday
3 <-> Thursday
4 <-> Friday

Then, a formula that match the previous calculus would be:然后,与之前的微积分匹配的公式将是:

Week_Day - X days => Week_Day - X days + 2 * CEIL((X - INDEX_OF(Week_Day)) / 5) days

where INDEX_OF() is a function that returns the previous indexing for days.

Example 1)示例 1)

Suppose we need to subtract 2 days from Wednesday, then the previous formula will reduce to this:假设我们需要从星期三减去 2 天,那么之前的公式将减少为:

"Wed" - 2 days => "Wed" - 2 + 2 * CEIL((2 - 2) / 5)
"Wed" - 2 days => "Wed" - 2 + 2 * CEIL(0 / 5)
"Wed" - 2 days => "Wed" - 2 + 2 * 0
"Wed" - 2 days => "Wed" - 2 + 0
"Wed" - 2 days => "Wed" - 2 days

Example 2)例 2)

Suppose we need to subtract 8 days from Wednesday (in this case we have two weekends in the middle of the subtract) then the previous formula will reduce to this:假设我们需要从星期三减去 8 天(在这种情况下,我们在减去中间有两个周末),那么前面的公式将减少为:

"Wed" - 8 days => "Wed" - 8 + 2 * CEIL((8 - 2) / 5)
"Wed" - 8 days => "Wed" - 8 + 2 * CEIL(6 / 5)
"Wed" - 8 days => "Wed" - 8 + 2 * 2 /* Two weekends are affecting */
"Wed" - 8 days => "Wed" - 8 + 4
"Wed" - 8 days => "Wed" - 12 days

So, based on this formula and manipulating the MySQL DAYOFWEEK() method for generate our INDEX_OF() function, we can do the next query:因此,基于此公式并操作 MySQL DAYOFWEEK()方法来生成我们的INDEX_OF()函数,我们可以执行下一个查询:

SELECT
    date AS OriginalDate,
    DAYOFWEEK(date) - 2 AS IndexOfDay,
    days_to_subtract AS DaysToSubtract,
    2 * CEIL((days_to_subtract - (DAYOFWEEK(date) - 2)) / 5) AS WeekendDaysToAdd,
    DATE_SUB(
        date,
        INTERVAL days_to_subtract + (2 * CEIL((days_to_subtract -  (DAYOFWEEK(date) - 2)) / 5)) DAY
    ) AS CalucaltedDay
FROM
    myTable

The last column CalculatedDay will contain the date you expect to obtain from the subtract, the others columns are just for check the steps of the mathematical calculus.最后一列CalculatedDay将包含您希望从减法中获得的日期,其他列仅用于检查数学演算的步骤。 I hope you can understand the logic behind this, because it costme some time to figure it out and try to explain it.我希望你能理解这背后的逻辑,因为我花了一些时间来弄清楚并试图解释它。 You can see working examples on next links:您可以在下一个链接上看到工作示例:

1) DB Fiddle 1)数据库小提琴

2) SQL Fiddle 2) SQL小提琴

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM