我正在尝试对某些日期进行减法运算,在我的特定情况下,我只需要减去工作日(不包括周末,即星期日和星期六)
我的表格是这样的:
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
我的目标是通过从 date 中减去 days_to_sub 来计算新列(新日期),仅考虑工作(劳动)天数并排除(或忽略)周末。
我试过这样的:
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"
但是当减去的天数大于5时,这将不起作用。
有没有使用简单的 SQL 而不使用复杂的函数来解决这个问题的建议?
最佳答案
让我们先解释一下您的情况:
Monday) 假设我们定位在星期一,那么当减去 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 */
...
星期二) 假设我们定位在星期二,那么当减去 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) 假设我们定位在星期三,那么当减去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 */
...
我们可以注意到,在这个逻辑中间有一个数学演算。如果我们以这种方式索引星期几:
0 <-> Monday
1 <-> Tuesday
2 <-> Wednesday
3 <-> Thursday
4 <-> Friday
然后,与前面的演算匹配的公式将是:
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.
示例 1)
假设我们需要从星期三减去 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
示例 2)
假设我们需要从星期三减去 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
因此,基于此公式并操纵 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
最后一列CalculatedDay 将包含您希望从减法中获得的日期,其他列仅用于检查数学演算的步骤。我希望你能理解这背后的逻辑,因为我花了一些时间来弄清楚并尝试解释它。您可以在下一个链接中查看工作示例:
1) DB Fiddle
2) SQL Fiddle
关于mysql - 从忽略周末的日期中减去天数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53015876/