首页 > 解决方案 > 没有周末的日期倒退

问题描述

我经常使用它query1在可变日期返回 6 天:

query1 = SELECT
    DATE_FORMAT((DATE('2018-11-21') - INTERVAL(S.`I` - 1) DAY), '%Y-%m-%d')
    AS VAR
    FROM `HELPER_SEQ`
    AS S WHERE S.`I` <= 6;

在此辅助表的帮助下,插入了一个序列。

CREATE TABLE `HELPER_SEQ` (`I` tinyint(3) UNSIGNED NOT NULL);
INSERT INTO `HELPER_SEQ` (`I`) VALUES (1),(2),(3),(4),(5),(6);

问题:

如何避免使用 query1 输出周末?以这样的方式,输出会在 6 个有用的日子里返回,在这个例子中,从 '2018-11-21' 开始,输出将是 ->

| 2018-11-21 | 
| 2018-11-20 |
| 2018-11-19 | 
| 2018-11-16 | 
| 2018-11-15 | 
| 2018-11-14 |

标签: mysql

解决方案


我们可以利用DayName()函数来获取日期对应的工作日名称。我们将利用此函数的结果将周末限制为NOT IN ('Saturday', 'Sunday').

此外,我们需要将数字生成器范围增加到10。因为我们有可能在 5 个工作日的任一侧遇到 2 个周末(共 4 天)。

因此,我们需要 2(第一对周末)+ 5(工作日)+ 2(第二对周末)+ 1(第 6 个工作日)= 10 个日期来考虑。这种极端情况的一个例子是输入日期是星期日。

LIMIT 6在非边缘情况下,我们将需要使用将结果限制为最多 6 天。

架构(MySQL v5.7)

CREATE TABLE `HELPER_SEQ` (`I` tinyint(3) UNSIGNED NOT NULL);
INSERT INTO `HELPER_SEQ` (`I`) VALUES 
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10);

询问

SELECT
    DATE_FORMAT((DATE('2018-11-21') - INTERVAL(S.`I` - 1) DAY), '%Y-%m-%d')
    AS VAR
FROM `HELPER_SEQ` AS S 
WHERE S.`I` <= 10 
  AND DAYNAME(DATE_FORMAT((DATE('2018-11-21') - INTERVAL(S.`I` - 1) DAY), '%Y-%m-%d')) NOT IN ('SATURDAY', 'SUNDAY')
ORDER BY VAR DESC
LIMIT 6;

结果

| VAR        |
| ---------- |
| 2018-11-21 |
| 2018-11-20 |
| 2018-11-19 |
| 2018-11-16 |
| 2018-11-15 |
| 2018-11-14 |

在 DB Fiddle 上查看


边缘案例演示 - 输入日期:2018 年 11 月 25 日(星期日)

CREATE TABLE `HELPER_SEQ` (`I` tinyint(3) UNSIGNED NOT NULL);
INSERT INTO `HELPER_SEQ` (`I`) VALUES 
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10);

查询 #2

SELECT
    DATE_FORMAT((DATE('2018-11-25') - INTERVAL(S.`I` - 1) DAY), '%Y-%m-%d')
    AS VAR
FROM `HELPER_SEQ` AS S 
WHERE S.`I` <= 10 
  AND DAYNAME(DATE_FORMAT((DATE('2018-11-25') - INTERVAL(S.`I` - 1) DAY), '%Y-%m-%d')) NOT IN ('SATURDAY', 'SUNDAY')
ORDER BY VAR DESC
LIMIT 6;

结果

| VAR        |
| ---------- |
| 2018-11-23 |
| 2018-11-22 |
| 2018-11-21 |
| 2018-11-20 |
| 2018-11-19 |
| 2018-11-16 |

在 DB Fiddle 上查看


推荐阅读