什么是MySQL替代Oracle的下一天功能?

什么是MySQL替代Oracle的下一天功能?,mysql,sql,database,oracle,Mysql,Sql,Database,Oracle,NEXT_DAY01-SEP-95,FRIDAY返回下周五的日期,但是在MySQL中这个函数似乎没有出现。还有什么选择?在MySQL中,您可以创建用户定义的函数 DELIMITER //   CREATE FUNCTION next_day(start_date DATETIME, weekday CHAR(20)) RETURNS DATETIME BEGIN DECLARE start DATETIME; DECLARE i INT;   // Sel

NEXT_DAY01-SEP-95,FRIDAY返回下周五的日期,但是在MySQL中这个函数似乎没有出现。还有什么选择?

在MySQL中,您可以创建用户定义的函数

DELIMITER //
 
  CREATE FUNCTION next_day(start_date DATETIME, weekday CHAR(20))
    RETURNS DATETIME
  BEGIN
    DECLARE start DATETIME;
    DECLARE i INT;
 
    // Select the next date
    SET start = ADDDATE(start_date, 1);
    SET i = 1;
 
    days: LOOP
          -- Compare the day names
        IF SUBSTR(DAYNAME(start), 1, 3) = SUBSTR(weekday, 1, 3) THEN    
       LEAVE days;
        END IF;
 
        // Select the next date
        SET start = ADDDATE(start, 1);
        SET i = i + 1;
 
        -- Not valid weekday specified
        IF i > 7 THEN
       SET start = NULL;
       LEAVE days;
    END IF;
 
     END LOOP days;
 
     RETURN start;
  END;
  //
 
   DELIMITER ;
叫它

SELECT NEXT_DAY("1995-09-01","FRIDAY")

来源:

以下是一个不同问题的答案:

查找当前星期五的日期:-

SELECT STR_TO_DATE(CONCAT('2017',(SELECT DATE_FORMAT(CURDATE(),'%U')),' Friday'),'%Y %U %W') x;
+------------+
| x          |
+------------+
| 2017-05-12 |
+------------+
上述内容的健壮性尚未得到验证,但“按原样”提供只是为了供思考

MySQL 5.6架构设置:

问题1:

简短版本:

利用DAYOFWEEK,您可以利用数值创建一个封闭公式,告诉您要添加多少天。然后,您可以利用DATE_ADD来帮助更改日期。可能有一种更干净的方法,但是您应该能够利用它来实现功能

下面是一个Excel公式,用于验证所有49个用例:=modnext输入,7+7,7

excel计算如何转换为SQL的一些示例:

SELECT (((1-DAYOFWEEK('2018-08-15')) % 7)+7) % 7 AS DaysToAddToGetNextSundayFromWednesday 
FROM dual; -- 4

SELECT DATE_ADD('2018-08-15', INTERVAL (((1-DAYOFWEEK('2018-08-15')) % 7)+7) % 7 DAY) AS NextSundayFromDate 
FROM dual; -- 2018-08-19   
如果您计划经常使用上述功能,您可能需要创建一个函数或存储过程

长版本:

多年来,我多次遇到这个问题。我第一次为所有49个案例创建了一个巨大的案例陈述。我发现这使得查询变得超级大而且不干净。我想要一个更干净、更简单的解决方案,比如封闭式公式。下面是详细的计算,我做了确认上述公式的工程。我用MySQL5.7测试了这一点,如果您使用的是MySQL8.5,那么该函数似乎是内置的引用:

注意:Excel不会为模数返回负结果,MySQL会返回负结果。这就是为什么我们加7,再做一个模数


我将用另一种方法在拳击场上大发雷霆:

编辑:我后来才意识到,所讨论的Oracle函数将字符串作为第二个参数,因此这并不完全符合要求。然而,MySQL已经善意地将0-6定义为星期一-星期天,无论如何,我在道义上反对使用字符串作为此类事件的参数。字符串可能来自用户输入,也可能来自更高级别代码中数值和字符串值之间的另一个映射。为什么不传递一个整数呢

要分解确定间隔值的部分,请执行以下操作:

方程式的第一部分仅获取指定的工作日和指定日期的工作日之间的偏移量:

p_weekday - WEEKDAY(p_date)
如果p_weekday大于weekday p_date,则返回正数,反之亦然。如果它们相同,则返回零

圆段用于确定相对于指定的p_日期,请求的周p_工作日是否已在当前周中出现。所以,举个例子

ROUND(WEEKDAY('2019-01-25') / (6 + WEEKDAY('2019-01-25') + 1))
..返回0,表示本周未发生星期日6,因为2019-01-25是星期五。同样地

ROUND(WEEKDAY('2019-01-25') / (2 + WEEKDAY('2019-01-25') + 1))
…返回1,因为星期三2已过。请注意,如果p_weekday与p_date的工作日相同,则返回0

然后将该值1或0乘以常数7,即一周中的天数

因此,如果p_weekday已经发生在当前周中,它将在偏移p_weekday-weekday p_date中添加7,因为偏移量将是负数,我们希望在将来有一个日期

如果p_weekday尚未出现在当前周中,那么我们可以将偏移量添加到当前日期,因为偏移量将是正数。因此,这一部分是圆的…*7等于零,本质上被忽略

我对这种方法的期望是从数学上模拟IF条件。这同样有效:


为了客观起见,在每个函数运行1M次迭代时,基于IF的版本平均比基于ROUND的版本快4.2%。

这意味着没有内置函数可以得到结果?@Madhivanan-我不是MySQL用户,但为什么不直接使用ADDDATEstart,如果日名相同,那么我们就好了。这个循环似乎有点过头了。诚然,我可能错过了一个MySQL技巧,因为我没有使用过这个技巧。我可以在网上看到一些实现,但我同意它们看起来都有点麻烦。我怀疑这里有人能做得更好——尽管自定义函数的想法也不错。你可能想指定这是针对MySQL 5.7或8.5之前的版本?
DAYOFWEEK()         
Sun     1       
Mon     2       
Tues    3       
Wed     4       
Thur    5       
Fri     6       
Sat     7       

Input   Next    Expected Days to Add    Formula Result
1       1       0                       0
1       2       1                       1
1       3       2                       2
1       4       3                       3
1       5       4                       4
1       6       5                       5
1       7       6                       6
2       1       6                       6
2       2       0                       0
2       3       1                       1
2       4       2                       2
2       5       3                       3
2       6       4                       4
2       7       5                       5
3       1       5                       5
3       2       6                       6
3       3       0                       0
3       4       1                       1
3       5       2                       2
3       6       3                       3
3       7       4                       4
4       1       4                       4
4       2       5                       5
4       3       6                       6
4       4       0                       0
4       5       1                       1
4       6       2                       2
4       7       3                       3
5       1       3                       3
5       2       4                       4
5       3       5                       5
5       4       6                       6
5       5       0                       0
5       6       1                       1
5       7       2                       2
6       1       2                       2
6       2       3                       3
6       3       4                       4
6       4       5                       5
6       5       6                       6
6       6       0                       0
6       7       1                       1
7       1       1                       1
7       2       2                       2
7       3       3                       3
7       4       4                       4
7       5       5                       5
7       6       6                       6
7       7       0                       0
CREATE FUNCTION `fnDayOfWeekGetNext`(
        p_date DATE,
        p_weekday TINYINT(3)
        ) RETURNS date
BEGIN

        RETURN DATE_ADD(p_date, INTERVAL p_weekday - WEEKDAY(p_date) + (ROUND(WEEKDAY(p_date) / (p_weekday + WEEKDAY(p_date) + 1)) * 7) DAY);

END
p_weekday - WEEKDAY(p_date)
ROUND(WEEKDAY('2019-01-25') / (6 + WEEKDAY('2019-01-25') + 1))
ROUND(WEEKDAY('2019-01-25') / (2 + WEEKDAY('2019-01-25') + 1))
RETURN DATE_ADD(p_date, INTERVAL p_weekday - WEEKDAY(p_date) + IF(p_weekday - WEEKDAY(p_date) < 0, 7, 0) DAY);