mysql根据记录当前日期确定未来日期

Posted

技术标签:

【中文标题】mysql根据记录当前日期确定未来日期【英文标题】:mysql determine future dates based on records current date 【发布时间】:2020-01-30 16:17:24 【问题描述】:

我对此进行了很多研究,但找不到任何与我的问题相关的内容,因此我发布了有关寻找方法的帮助和指导方案 - 如果可能的话,请指出我正确的方向。与下面的一些 cmets 不同,我不太清楚如何提供最小可重现查询,尤其是因为我不知道它是否可能。

我有一个保存事件记录的 mysql 表。每条记录都定义了事件的开始时间 (startDate) - 例如:2019 年 9 月 4 日(星期三)。该事件应该在那之后的每个星期三重复 - 但只有一个主事件记录。 eventFreq 指定事件应该发生的频率。

eventFreq = 1 ; // every x day of week (every Wednesday)
eventFreq = 2 ; // every other x day of week (every other Monday)
eventFreq = 3 ; // every 3rd X day of month (every 3rd Tuesday)

是否可以编写一个 mysql 查询,根据主记录 startDateeventFreq,为我提供未来一个月内星期三的所有实例(即:2020 年 3 月的所有星期三)?或者根据今天的当前日期给我下一个星期三的查询。这些查询需要确定 startDate 是从星期三开始,以便确定未来的查询。

如果它确定了 2020 年 3 月的未来星期三,它将返回主事件记录以及特定未来星期三的额外字段。

主事件记录:ID,eventName,eventDescription,startDate,eventFreq,blah1,blah2,blah3

如果找到 3 月的星期三,它将返回整个记录,并添加一个列 nextDate 作为 3 月的星期三之一。因此它会返回相同的四个记录,并附加一个nextDate 列。

粗略地说:

   IF DATE == Wednesday, then Date as nextDate  
OR IF Wednesday BETWEEN FirstDayOfMonth AND LastDayOfMonth  
OR IF Wednesday, then Next Wednesday after today

将返回相同的主记录 X 次,并附加列 nextDate

ID,eventName,eventDescription,startDate,eventFreq,blah1,blah2,blah3,nextDate // March 4 2020
ID,eventName,eventDescription,startDate,eventFreq,blah1,blah2,blah3,nextDate // March 11 2020 
ID,eventName,eventDescription,startDate,eventFreq,blah1,blah2,blah3,nextDate // March 18 2020
ID,eventName,eventDescription,startDate,eventFreq,blah1,blah2,blah3,nextDate // March 25 2020

目前我正在提取所有事件并使用 php 处理所有事件 startDateeventFreq(每个星期三)以确定未来的星期三。对于所有各种场景,代码都是广泛而复杂的 - 所以我希望一个好的 mysql 查询只会返回正确的未来日期,然后我所要做的就是处理结果。

这可以实现吗?

【问题讨论】:

我将使用 DateTime 的两列来解决这个问题,这将是 - initialDt,currentDt。然后使用 Cron 作业将更新 currentDt。我将应用的任何检查都将取决于 currentDt 列,即必须重复事件的最晚日期。 如果您将鼠标悬停在 dv 按钮上,它会将“不清楚”作为拒绝投票的理由。这还不清楚,因此 dv.说清楚,dv就会神奇消失;皱眉甚至可以变成微笑。 “每隔一个”是什么意思?应该从月初算起(比如第 1 和第 3 个星期一不匹配,但第 2 和第 4 个星期一应该匹配)还是从第一个输入日期算起? @fifonik - 有三种类型的事件:每周。每隔一周和每月一次。 “每隔一个” - 表示距下一个日期还有 14 天。 “每月一次”= 每月的第二个星期一。 2020:“每隔一个”星期三将在 1/01、15/01、29/01,对吗?那么,它也应该在 05/02 上吗?如果是这样,它不是之前 29/01 的“每隔一个”吗?我的意思是在没有更多细节的情况下理解您的要求有点棘手。可能有些重命名会有所帮助,例如“每隔一个”=>“本月的偶数/奇数周”。 【参考方案1】:

我认为你试图在一个篮子里放太多东西。你应该把它们分开。

    您可以使用日期时间计算函数来确定您感兴趣的日期范围

    然后您可以使用one of the ways 生成该日期范围内的日期列表

    您可以选择按一些通用标准过滤日期(例如,如果需要,不包括星期日或公共假期)

    最后,您可以测试列表中的每个日期是否符合您的 eventFreq 标准。这可以实现为一个函数,如下所示:

CREATE FUNCTION `SP_IsEventFreqMatched`(
    `aDateRef` DATE,
    `aEventFreq` TINYINT UNSIGNED,
    `aDate` DATE
)
RETURNS TINYINT(1) UNSIGNED
DETERMINISTIC
BEGIN
    SET @r = DAYOFWEEK(aDate) = DAYOFWEEK(aDateRef);
    IF @r = 1 THEN
        CASE aEventFreq
            WHEN 1 THEN
                BEGIN
                    -- every x day of week (every Wednesday)
                    -- weekdays already matched. do nothing
                END;

            WHEN 2 THEN
                BEGIN
                    -- every other x day of week (every other Monday)
                    SET @r = (ABS(DATEDIFF(aDate, aDateRef)) / 7) MOD 2 = 0;
                END;

            WHEN 3 THEN
                BEGIN
                    -- every 3rd X day of month (every 3rd Tuesday)
                    SET @r = (ABS(DATEDIFF(aDate, aDateRef)) / 7) MOD 3 = 0;
                END;

            -- You can add logic other eventFreq types

            ELSE
                BEGIN
                    -- todo@ raise an error? 
                    SET @r = 0; 
                END;
        END CASE;
    END IF;

    RETURN @r;
END

所以,最后你的查询看起来像这样(我正在使用我的技术来生成范围内的日期,你可以在提供的链接上找到它):

SET @from = '2020-02-15';
SET @to   = '2020-03-15';

SELECT
      m.ID
    , m.startDate
    , DAYOFWEEK(m.startDate) - 1 AS weekday
    , m.eventFreq
    , d.d AS nextDate
FROM
      `global`.dates AS d
    , `Master` AS m
WHERE
        d.d BETWEEN @from AND @to
    AND SP_IsEventFreqMatched(m.startDate, m.eventFreq, d.d)
ORDER BY
      m.eventFreq
    , d.d
;

=>

ID  startDate   weekday eventFreq   nextDate
1   2020-01-01  3   1   2020-02-19
1   2020-01-01  3   1   2020-02-26
1   2020-01-01  3   1   2020-03-04
1   2020-01-01  3   1   2020-03-11
2   2020-01-02  4   2   2020-02-27
2   2020-01-02  4   2   2020-03-12
3   2020-01-03  5   3   2020-03-06

注 1:为简单起见,我使用会话变量来指定日期范围。在现实生活中,您可能应该根据您的搜索条件或从当前日期计算它。

注2:我不明白你想如何计算“每隔一个”。从日期的月初开始或从 startDate 记录开始。我在 SP 中实现了后者。如果你需要另一个,你必须调整功能。

【讨论】:

感谢您的广泛响应。它给了我很多思考和思考。

以上是关于mysql根据记录当前日期确定未来日期的主要内容,如果未能解决你的问题,请参考以下文章

MySQL日期类型

无法根据日期字段获取记录 = jhipster 中的当前日期

mysql记录根据日期字段倒序输出

SQL 根据当前日期减去两天选择记录

Mysql 查询获取日期时间紧跟当前日期时间之后的记录

MySQL计算当前连续日期的连续日期