2017-05-08 263 views
0

我有表TableName它包含大约5,000行。它由一个product_id和一个ScheduleTime组成。试图使用DATEADD和获取函数不存在错误

我想用这个表格替换每个值ScheduleTime,不管它现在是什么。每条记录的新值ScheduleTime应设置为前一记录后分钟的提名值,但有以下例外情况。如果代名人ScheduleTime发生在22:30:00之后或05:00:00之前(即太晚或太早),则应将其设置为下一个可用日期时间。

我应该能够指定第一个新值ScheduleTime将是什么。

这是我使用的那一刻

#1305 - FUNCTION DatabaseName.DATEADD does not exist 

此查询可用于创建查询...

UPDATE TableName 
SET ScheduleTime = DATEADD(MI, ScheduleTime, 20) 
WHERE CAST(ScheduleTime AS TIME) >= '22:30:00' 
    OR CAST(ScheduleTime AS TIME) < '05:00:00'; 

但它产生此错误消息...表,我有...

CREATE TABLE IF NOT EXISTS TableName 
(
    product_id VARCHAR(255) NOT NULL, 
    ScheduleTime DATETIME NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

我使用下面的示例数据填充上表...

INSERT INTO TableName (product_id, 
         ScheduleTime) 
VALUES ('01', '2017-05-07 22:00:59'), 
     ('02', '2017-05-07 09:09:59'), 
     ('03', '2017-05-07 09:59:59'), 
     ('04', '2017-05-07 09:49:59'), 
     ('05', '2017-05-07 23:09:59'), 
     ('06', '2017-05-07 23:09:59'), 
     ('07', '2017-05-07 23:09:59'), 
     ('08', '2017-05-07 23:09:59'), 
     ('09', '2017-05-07 23:09:59'), 
     ('10', '2017-05-07 23:09:59'), 
     ('11', '2017-05-07 23:09:59'), 
     ('12', '2017-05-07 23:09:59'), 
     ('13', '2017-05-07 23:09:59'), 
     ('14', '2017-05-07 23:09:59'), 
     ('15', '2017-05-07 23:09:59'), 
     ('16', '2017-05-07 23:09:59'), 
     ('17', '2017-05-07 23:09:59'), 
     ('18', '2017-05-07 23:09:59'), 
     ('19', '2017-05-07 23:09:59'), 
     ('20', '2017-05-07 23:09:59'); 
+0

尝试'DATE_ADD(ScheduleTime,间隔的20分钟)'(注意'_')。请阅读https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-add。 – toonice

+0

另外,“MI”是什么意思? – toonice

+0

@toonice MI被静置分钟,当我使用'UPDATE数据库 SET ScheduleTime = DATE_ADD(ScheduleTime,INTERVAL 20 MINUTE) 其中CAST(ScheduleTime作为时间)<'22:30:00' 或CAST(ScheduleTime随着时间的)> = '05:00:00'; '它不会给我错误,但它也不会改变表中的任何内容 – Schwann

回答

1

请通过每个记录循环,增加20minutes到对前一个记录的ScheduleTime字段中的值尝试以下...

SET @workingScheduleTime := (SELECT DATE_ADD('2017-05-06 22:00:59', INTERVAL -20 MINUTE)); 
UPDATE TableName 
JOIN (SELECT product_id, 
       CASE 
        WHEN TIME(DATE_ADD(@workingScheduleTime, INTERVAL 20 MINUTE)) NOT BETWEEN '05:00:01' and '22:29:59' THEN 
         @workingScheduleTime := DATE_ADD(TIMESTAMP(DATE(@workingScheduleTime), '05:00:01'), INTERVAL 1 DAY) 
        ELSE 
         @workingScheduleTime := DATE_ADD(@workingScheduleTime, INTERVAL 20 MINUTE) 
       END AS ScheduleTime 
     FROM TableName 
    ) AS redatedList ON TableName.product_id = redatedList.product_id 
SET TableName.ScheduleTime = redatedList.ScheduleTime; 

此通过作品的解决方案。它还允许指定初始值ScheduleTime。因此,我们需要开始工作值ScheduleTime20minutes之前我们的初始值,以便循环的第一次迭代将返回我们的初始值。因此,我的解决方案开始与声明...

SET @workingScheduleTime := (SELECT DATE_ADD('2017-05-06 22:00:59', INTERVAL -20 MINUTE)); 

随着我们的工作价值从而初始化我一直在使用基于在MySQL - UPDATE query based on SELECT Query发现Eric的解决方案SELECT语句实现表TableNameUPDATE。声明如下...

UPDATE TableName 
JOIN (SELECT product_id, 
       CASE 
        WHEN TIME(DATE_ADD(@workingScheduleTime, INTERVAL 20 MINUTE)) NOT BETWEEN '05:00:01' and '22:29:59' THEN 
         @workingScheduleTime := DATE_ADD(TIMESTAMP(DATE(@workingScheduleTime), '05:00:01'), INTERVAL 1 DAY) 
        ELSE 
         @workingScheduleTime := DATE_ADD(@workingScheduleTime, INTERVAL 20 MINUTE) 
       END AS ScheduleTime 
     FROM TableName 
    ) AS redatedList ON TableName.product_id = redatedList.product_id 
SET TableName.ScheduleTime = redatedList.ScheduleTime; 

本声明基于的product_id他们共同的价值以下子查询的结果执行TableNameINNER JOIN之间的一个实例启动...

SELECT product_id, 
     CASE 
      WHEN TIME(DATE_ADD(@workingScheduleTime, INTERVAL 20 MINUTE)) NOT BETWEEN '05:00:01' and '22:29:59' THEN 
       @workingScheduleTime := DATE_ADD(TIMESTAMP(DATE(@workingScheduleTime), '05:00:01'), INTERVAL 1 DAY) 
      ELSE 
       @workingScheduleTime := DATE_ADD(@workingScheduleTime, INTERVAL 20 MINUTE) 
      END AS ScheduleTime 
FROM TableName 

这子查询为TableName中的每个记录选择product_id的值,然后检查工作值的下一个值是否将在发起人禁止的时间范围内发生为太晚/太早。如果确实如此,则CASE声明选择下一个可接受的时间(第二天的05:00:01)。如果被提名人的价值在可接受的时间范围内,则由CASE声明选择。工作值更新

然后将CASE语句选择的值选为子查询的新值ScheduleTime

如上所述,子查询的结果然后以这样的方式加入到TableName中,使得每个现有记录TableName有效地具有它附加的新值。 SET声明使用此新建立的关系将每个现有值ScheduleTime更改为其相应的新值。

这个答案对利用问题的CREATE声明和填充使用下面的脚本创建数据测试...

INSERT INTO TableName (product_id, 
         ScheduleTime) 
VALUES ('01', '2017-05-07 22:00:59'), 
     ('02', '2017-05-07 09:09:59'), 
     ('03', '2017-05-07 09:59:59'), 
     ('04', '2017-05-07 09:49:59'), 
     ('05', '2017-05-07 23:09:59'), 
     ('06', '2017-05-07 23:09:59'), 
     ('07', '2017-05-07 23:09:59'), 
     ('08', '2017-05-07 23:09:59'), 
     ('09', '2017-05-07 23:09:59'), 
     ('10', '2017-05-07 23:09:59'), 
     ('11', '2017-05-07 23:09:59'), 
     ('12', '2017-05-07 23:09:59'), 
     ('13', '2017-05-07 23:09:59'), 
     ('14', '2017-05-07 23:09:59'), 
     ('15', '2017-05-07 23:09:59'), 
     ('16', '2017-05-07 23:09:59'), 
     ('17', '2017-05-07 23:09:59'), 
     ('18', '2017-05-07 23:09:59'), 
     ('19', '2017-05-07 23:09:59'), 
     ('20', '2017-05-07 23:09:59'); 

我的代码,结果被证实由提问者为宜。

进一步阅读

https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_between(对MySQL的BETWEENNOT BETWEEN运营商)

https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date(对MySQL的DATE()功能)

https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-add(对MySQL的DATE_ADD()功能)

https://dev.mysql.com/doc/refman/5.7/en/set-statement.html(上MySQL的的SET语句)

https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_time(对MySQL的TIME()功能)

https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_timestamp(对MySQL的TIMESTAMP()功能)

https://dev.mysql.com/doc/refman/5.7/en/update.html(对MySQL的UPDATE语句)

+0

感谢您花费数小时的时间为我解决这个问题。我不能说我多么感激这一点。该代码完美无瑕地工作,它甚至可以选择定义自定义开始时间和日期。 – Schwann

+0

不客气。乐意效劳。我将很快添加一个解释。 – toonice

+0

添加说明。此外,还发现了一个错误。之前,当它在被禁止的时间范围内发现被提名人ScehduleTime值时,它将时间分量设置为05:00:01,并将日期分量设置为*相同*日,而不是*下一天*有。此错误现已在我的答案中得到纠正。如果这造成了不便,我很抱歉。 – toonice

相关问题