我正在尝试编写一个存储函数,该函数采用正确的ISO格式(yyyy-mm-dd)字符串,并从中减去一定数量的工作日。基于this question here我已经尝试了接受的答案以及一些答案,这些答案的方式不同,但是,他们都只是在说如何编写纯粹的SQL,而且没有一个函数的例子。
我现在拥有的是:
delimiter //
CREATE DEFINER=`root`@`localhost` FUNCTION `WEEKDATE_SUB` (days TINYINT, date_val VARCHAR(16))
RETURNS DATE DETERMINISTIC
BEGIN
DECLARE SUBVAL INT;
DECLARE dow INT;
CASE
WHEN dow=1 THEN SET SUBVAL = (days +(FLOOR((days-0.5)/5)+1)*2 - 1);
WHEN dow=2 THEN SET SUBVAL = (days +(FLOOR((days-0.5)/5)+1)*2);
WHEN dow=3 THEN SET SUBVAL = (days-1 +(FLOOR(((days-1)-0.5)/5)+1)*2 + 1);
WHEN dow=4 THEN SET SUBVAL = (days-2 +(FLOOR(((days-2)-0.5)/5)+1)*2 + 2);
WHEN dow=5 THEN SET SUBVAL = (days-3 +(FLOOR(((days-3)-0.5)/5)+1)*2 + 3);
WHEN dow=6 THEN SET SUBVAL = (days-4 +(FLOOR(((days-4)-0.5)/5)+1)*2 + 4);
WHEN dow=7 THEN SET SUBVAL = (days-5 +(FLOOR(((days-5)-0.5)/5)+1)*2 + 5);
END CASE
RETURN DATE_SUB(date_val, INTERVAL SUBVAL DAY);
END;//
当我尝试添加它时,我得到一个模糊的错误(因为mysql喜欢提供): 您的SQL语法有错误;检查与您的MariaDB服务器版本对应的手册,以便在< RETURN DATE_SUB(date_val,INTERVAL SUBVAL DAY)附近使用正确的语法; END'在第14行
我已经尝试了几种关于返回的变体,包括尝试为Date sub定义变量并返回它,但它几乎是相同的错误。
在一个函数之外,我知道这个有效,所以看起来我应该能够返回它。
SELECT DATE_SUB("2016-01-01", INTERVAL 4 DAY);
答案 0 :(得分:1)
文档建议您需要END CASE,而不是END
此外,如果使用CASE expr WHEN value2 THEN .... WHEN value2 THEN ... END CASE
版本,存储的函数可能会执行得更快,因为它不必重复DAYOFWEEK函数调用7次。
答案 1 :(得分:1)
你也可以使用这样的东西
delimiter //
CREATE DEFINER=`root`@`localhost` FUNCTION `WEEKDATE_SUB` (date_val VARCHAR(10), days TINYINT)
RETURNS VARCHAR(10) DETERMINISTIC
BEGIN
RETURN date_val - INTERVAL
FLOOR(days/5)*7 +
IF(DAYOFWEEK(date_val)-1 <= days - FLOOR(days/5)*5
, (days - FLOOR(days/5)*5)+2
, days - FLOOR(days/5)*5
) DAY;
END;//
<强>样品强>
mysql> SELECT WEEKDATE_SUB('2017-02-06',1);
+------------------------------+
| WEEKDATE_SUB('2017-02-06',1) |
+------------------------------+
| 2017-02-03 |
+------------------------------+
1 row in set (0,00 sec)
mysql> SELECT WEEKDATE_SUB('2017-02-07',1);
+------------------------------+
| WEEKDATE_SUB('2017-02-07',1) |
+------------------------------+
| 2017-02-06 |
+------------------------------+
1 row in set (0,00 sec)
mysql> SELECT WEEKDATE_SUB('2017-02-07',2);
+------------------------------+
| WEEKDATE_SUB('2017-02-07',2) |
+------------------------------+
| 2017-02-03 |
+------------------------------+
1 row in set (0,00 sec)
mysql>
答案 2 :(得分:0)
这是我最终需要这个工作。注意,;以及对我如何使用CASE声明的更改。
delimiter //
CREATE DEFINER=`root`@`localhost` FUNCTION `WEEKDATE_SUB` (date_val VARCHAR(10), days TINYINT)
RETURNS VARCHAR(10) DETERMINISTIC
BEGIN
DECLARE SUBVAL INT;
DECLARE dow INT;
SET dow = DAYOFWEEK(date_val);
CASE dow
WHEN 1 THEN SET SUBVAL = (days +(FLOOR((days-0.5)/5)+1)*2 - 1);
WHEN 2 THEN SET SUBVAL = (days +(FLOOR((days-0.5)/5)+1)*2);
WHEN 3 THEN SET SUBVAL = (days-1 +(FLOOR(((days-1)-0.5)/5)+1)*2 + 1);
WHEN 4 THEN SET SUBVAL = (days-2 +(FLOOR(((days-2)-0.5)/5)+1)*2 + 2);
WHEN 5 THEN SET SUBVAL = (days-3 +(FLOOR(((days-3)-0.5)/5)+1)*2 + 3);
WHEN 6 THEN SET SUBVAL = (days-4 +(FLOOR(((days-4)-0.5)/5)+1)*2 + 4);
WHEN 7 THEN SET SUBVAL = (days-5 +(FLOOR(((days-5)-0.5)/5)+1)*2 + 5);
ELSE SET SUBVAL = days;
END CASE;
RETURN DATE_SUB(date_val, INTERVAL SUBVAL DAY);
END;//