我目前正在从较小的表中计算一个datetime列与另一datetime列的滞后变量之间的时间差。 然后将结果插入到更大的最终表中。 这是过程的一部分,其中我有一些较小的表作为csv,并且每个表都要计算滞后差并将其加载到最终表中(最终表大约为20GB,而12个较小的表大约为2.5GB )
我之前已经完成了几次没有滞后变量的单独插入,一切都很好。 但是,在表12中的6中,现在出现以下错误,我无法弄清原因:
ERROR 1292 (22007): Truncated incorrect time value: '2355:46:39.000000'
我可以提供一个适用于其余表的测试示例:
DROP TABLE IF EXISTS single_test;
CREATE TABLE single_test(
medallion VARCHAR(64),
hack_license VARCHAR(64),
pickup_datetime DATETIME,
dropoff_datetime DATETIME,
id INT NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO single_test VALUES
('a', '1' , '2013-01-06 00:18:35','2013-01-06 02:10:33',1),
('a', '1' , '2013-01-06 02:40:58','2013-01-06 03:40:01',2),
('b', '1' , '2013-01-06 04:07:21','2013-01-06 05:00:41',3),
('c', '1' , '2013-01-07 13:12:08','2013-01-07 13:32:27',4),
('a', '2', '2013-01-06 03:50:30','2013-01-06 04:22:13',5),
('a', '2', '2013-01-06 04:41:23','2013-01-06 04:57:04',6),
('d', '2', '2013-01-07 12:22:56','2013-01-07 13:02:14',7),
('d', '3', '2013-01-07 13:03:24','2013-01-07 15:47:31',8)
;
CREATE TABLE final_test(
medallion VARCHAR(64),
hack_license VARCHAR(64),
pickup_datetime DATETIME,
dropoff_datetime DATETIME,
id INT NOT NULL,
delta VARCHAR(20),
current_dropoff DATETIME,
current_hack VARCHAR(64),
PRIMARY KEY (id)
);
SET @quot= '000-00-00 19:19:19';
SET @current_hack = '';
INSERT INTO final_test
SELECT medallion, hack_license, pickup_datetime, dropoff_datetime, id,
IF(@current_hack = hack_license,TIMEDIFF(pickup_datetime, @quot),NULL) as delta,
@quot:= dropoff_datetime current_dropoff, @current_hack:= hack_license
FROM single_test ORDER BY hack_license, pickup_datetime;
结果看起来像这样:
SELECT * FROM final_test;
+-----------+--------------+---------------------+---------------------+----+-----------------+---------------------+--------------+
| medallion | hack_license | pickup_datetime | dropoff_datetime | id | delta | current_dropoff | current_hack |
+-----------+--------------+---------------------+---------------------+----+-----------------+---------------------+--------------+
| a | 1 | 2013-01-06 00:18:35 | 2013-01-06 02:10:33 | 1 | NULL | 2013-01-06 02:10:33 | 1 |
| a | 1 | 2013-01-06 02:40:58 | 2013-01-06 03:40:01 | 2 | 00:30:25.000000 | 2013-01-06 03:40:01 | 1 |
| b | 1 | 2013-01-06 04:07:21 | 2013-01-06 05:00:41 | 3 | 00:27:20.000000 | 2013-01-06 05:00:41 | 1 |
| c | 1 | 2013-01-07 13:12:08 | 2013-01-07 13:32:27 | 4 | 32:11:27.000000 | 2013-01-07 13:32:27 | 1 |
| a | 2 | 2013-01-06 03:50:30 | 2013-01-06 04:22:13 | 5 | NULL | 2013-01-06 04:22:13 | 2 |
| a | 2 | 2013-01-06 04:41:23 | 2013-01-06 04:57:04 | 6 | 00:19:10.000000 | 2013-01-06 04:57:04 | 2 |
| d | 2 | 2013-01-07 12:22:56 | 2013-01-07 13:02:14 | 7 | 31:25:52.000000 | 2013-01-07 13:02:14 | 2 |
| d | 3 | 2013-01-07 13:03:24 | 2013-01-07 15:47:31 | 8 | NULL | 2013-01-07 15:47:31 | 3 |
+-----------+--------------+---------------------+---------------------+----+-----------------+---------------------+--------------+
8 rows in set (0,00 sec)
相反,由于我希望TIMEDIFF截断任何无效的输入,因此ERROR消息没有多大意义:
# Extremely Large difference
SELECT TIMEDIFF("2013-01-01 19:00:00","1900-01-01 19:00:00");
+-------------------------------------------------------+
| TIMEDIFF("2013-01-01 19:00:00","1900-01-01 19:00:00") |
+-------------------------------------------------------+
| 838:59:59 |
+-------------------------------------------------------+
1 row in set, 1 warning (0,00 sec)
# Invalid/ unrealistic datetime format due to to high/ to low values
SELECT TIMEDIFF("2013-01-01 19:00:00","000-00-00 19:19:19");
+------------------------------------------------------+
| TIMEDIFF("2013-01-01 19:00:00","000-00-00 19:19:19") |
+------------------------------------------------------+
| 838:59:59 |
+------------------------------------------------------+
1 row in set, 1 warning (0,00 sec)
# Invalid/ unrealistic datetime format due to character in values
SELECT TIMEDIFF("2013-01-01 19:00:00","000-00-00T 19:19:19");
+-------------------------------------------------------+
| TIMEDIFF("2013-01-01 19:00:00","000-00-00T 19:19:19") |
+-------------------------------------------------------+
| NULL |
+-------------------------------------------------------+
1 row in set, 1 warning (0,00 sec)
我正在使用Mysql 5.7。
我还从字母中搜索了较小的数据以查找无效字符,但是什么也没找到。
最好的问候
PS:我知道这个SO线程,但是它没有提供任何帮助Error Code: 1292. Truncated incorrect time value
答案 0 :(得分:1)
可以使用以下脚本重现该问题:
create table test(
tdiff varchar(20)
);
set @dt1 = '1900-01-01 19:00:00';
set @dt2 = '2013-01-01 19:00:00';
select TIMEDIFF(@dt2, @dt1);
insert into test (tdiff) select TIMEDIFF(@dt2, @dt1);
当SELECT语句返回838:59:59
时,具有相同表达式的INSERT语句将引发错误:
错误:ER_TRUNCATED_WRONG_VALUE:截断了错误的时间值: '990552:00:00'
诸如此类的查询会遇到类似的问题
insert into test (tdiff) select cast('abc' as char(2));
或
insert into test (tdiff) select '9999-12-31' + interval 1 day;
而相应的SELECT语句将返回ab
和NULL
而没有错误。
错误的原因是STRICT_TRANS_TABLES
模式。我们可以争论一下,如果这种行为有意义的话-但我怀疑这种行为是否会改变。
那你能做什么?
insert ignore into test (tdiff) select TIMEDIFF(@dt2, @dt1);
在IGNORE
之后使用INSERT
会将这些错误转换为警告。这似乎是最简单的方法。
您可以仅针对一条语句禁用STRICT_TRANS_TABLES
模式:
set @old_sql_mode = @@sql_mode;
set session sql_mode = replace(@@sql_mode, 'STRICT_TRANS_TABLES', '');
<your INSERT statement here>;
set session sql_mode = @old_sql_mode;
由于有效范围是从-838:59:59
到+838:59:59
,因此我们可以检查小时数的绝对差是否小于839
-否则返回其他值:
insert into test (tdiff) select
case when abs(timestampdiff(hour, @dt2, @dt1)) < 839
then TIMEDIFF(@dt2, @dt1)
else 'out of range'
end
这是我首选的解决方案。使用TIMESTAMPDIFF()
以秒为单位计算差异:
insert into test (tdiff) select timestampdiff(second, @dt1, @dt2);
请注意,TIMESTAMPDIFF()
使用的参数顺序与TIMEDIFF()
不同。因此,如果要获得肯定的结果,则应将最小的DATETIME值排在第一位。
答案 1 :(得分:0)
摘自MySQL官方文档:
DATETIME类型用于包含日期和时间的值 部分。 MySQL检索并在'YYYY-MM-DD中显示DATETIME值 hh:mm:ss的格式。支持的范围是“ 1000-01-01 00:00:00”至 '9999-12-31 23:59:59'。
2355:46:39.00000 显然超出了00:00:00-23:59:59的支持范围。
class BlogListing(BaseListing):
subpage_types = ['BlogPost']
template = 'listing.html'
如果此查询的预期结果是 00:00:00 ,而不是 838:59:59 ,请尝试以下操作:
| TIMEDIFF("2013-01-01 19:00:00","1900-01-01 19:00:00") |
+-------------------------------------------------------+
| 838:59:59
来源:https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_time