2017-02-09 173 views
0

我正在尝试编写一个存储函数,该函数以正确的ISO格式(yyyy-mm-dd)获取一个字符串,并从中删除一定数量的工作日。基于this question here我已经尝试了接受的答案以及一些不同的做法,但是,它们都只是说如何编写纯sql,而没有函数的示例。DATE_SUB/DATE_ADD在存储函数中的返回值

我现在有是这样的:

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子句定义一个变量并返回它,但它几乎是相同的错误。

在功能之外,我知道这是有效的,所以看起来我应该能够返回它。

SELECT DATE_SUB("2016-01-01", INTERVAL 4 DAY); 

回答

1

该文档建议你需要有END CASE,而不是END

此外,存储功能将可能执行快一点,如果你使用CASE expr WHEN value2 THEN .... WHEN value2 THEN ... END CASE版本,因为它不会有重复的DAYOFWEEK函数调用可能有7次。

+0

我给您的建议一试。我很高兴你抓住了DAYOFWEEK的事情。它仍然会给出同样的错误。 –

+0

明白了。你让我走在正确的轨道上。以及END CASE,我需要一个; –

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;// 
+1

'dow'从来不会与您展示的内容一致。 – Uueerdo

+0

是的。它现在已经修复了,而且确实有效。 –

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>