我有一个数据库,其中包含每 30 分钟(+/- 3 秒)保存的数据。大约有 20 000 条记录。现在我想获取没有保存记录的所有日期时间:例如,我不想得到 2012-11-22 16:30 作为结果,因为它存在于数据库中。但是我想将 2012-11-22 16:00 作为一个,因为数据库不包含具有该日期的条目。
请记住,秒部分可能会有所不同。通常它恰好是在这一分钟,但有时它可能是 2012-05-10 10:00:03 左右。
我该如何做这样的查询?
我有一个数据库,其中包含每 30 分钟(+/- 3 秒)保存的数据。大约有 20 000 条记录。现在我想获取没有保存记录的所有日期时间:例如,我不想得到 2012-11-22 16:30 作为结果,因为它存在于数据库中。但是我想将 2012-11-22 16:00 作为一个,因为数据库不包含具有该日期的条目。
请记住,秒部分可能会有所不同。通常它恰好是在这一分钟,但有时它可能是 2012-05-10 10:00:03 左右。
我该如何做这样的查询?
我创建了一张表来显示我的存储过程。下面给出表创建查询
CREATE TABLE `testtable1` (
`id` INT(11) NULL DEFAULT NULL,
`timecol` DATETIME NULL DEFAULT NULL
)
表包含如下给出的数据
为了满足您的要求,我创建了以下存储过程
DELIMITER $$
CREATE PROCEDURE proc1(fromtime DATETIME,totime DATETIME)
BEGIN
DECLARE a INT Default 1;
DECLARE temptime DATETIME;
DECLARE ini,diff,nos int;
DECLARE temp1,temp6 datetime;
drop table if exists mytemptable;
CREATE TEMPORARY TABLE IF NOT EXISTS mytemptable ( `missing_dates` DATETIME NULL DEFAULT NULL);
if(minute(fromtime)>30) then
set diff=60-(minute(fromtime));
else
set diff=30-(minute(fromtime));
end if;
set temptime=ADDTIME(fromtime,concat('00:',diff,':00'));
while((unix_timestamp(totime)-unix_timestamp(temptime))>0) DO
set temp1=SUBTIME(temptime,'00:00:03');
set temp6=ADDTIME(temptime,'00:00:03');
select count(*) into nos from testtable1 where timecol>=temp1 and timecol<=temp6;
if(nos=0) then
insert into mytemptable (missing_dates) values (temptime);
end if;
set temptime=ADDTIME(temptime,'00:30:00');
END WHILE;
select * from mytemptable;
END $$
要获得所需的结果,只需使用“从时间”和“到时间”调用上述存储过程。例如
call proc1('2013-01-01 14:00:00','2013-01-01 17:00:00')
结果如下
如果您能够使用存储过程,那么您可以使用此存储过程来生成系统中最高日期和最低日期之间的日期时间范围。
如果您不能确定时间戳的每分钟粒度,那么您可能需要使用秒作为间隔而不是分钟。
针对该表的左连接应该显示数据尚未保存的日期和时间。
如果您正在寻找间隙,更简单的查询是查找下一个稍后时间不在 30 分 6 秒内的所有时间。
可以在特定总时间长度的单个查询中执行此操作。以下将使用 65536 的临时表检查给定范围内的丢失时间,甚至从 2010 年起 30 分钟(大约 3.7 年的时间):
select t
from (select date_add('2010-01-01', interval (a+4*b+16*c+64*d+256*e+1024*f+4096*g+16384*h)*30 minute) t from (select 0 a union select 1 union select 2 union select 3) a, (select 0 b union select 1 union select 2 union select 3) b, (select 0 c union select 1 union select 2 union select 3) c, (select 0 d union select 1 union select 2 union select 3) d, (select 0 e union select 1 union select 2 union select 3) e, (select 0 f union select 1 union select 2 union select 3) f, (select 0 g union select 1 union select 2 union select 3) g, (select 0 h union select 1 union select 2 union select 3) h order by t) ad_hoc_times
left join ( your_table, (select -3 t_adj union select -2 union select -1 union select 0 union select 1 union select 2 union select 3) t_adj )
on your_timestamp=date_add(t, interval t_adj second)
where t between '2010-07-01' and '2012-07-01'
and your_table.your_timestamp is null;
(您的时间戳字段必须被索引。)