繁体   English   中英

高效的 SQL 查询以查找连续数字数据中的间隙 (MySQL)

[英]Efficient SQL query to find gap in consecutive numeric data (MySQL)

我有一个包含“时间”列(INT 无符号)的表,每一行代表一秒钟,我需要及时找到间隔(丢失的秒数)。
我试过这个查询(在差距之前找到第一次):

SELECT t1.time
FROM `table` AS t1
LEFT JOIN `table` AS t2 ON t2.time=(t1.time+1)
WHERE t2.time IS NULL
ORDER BY TIME ASC
LIMIT 1

它有效,但对于大表(近 100M 行)来说太慢了
有没有更快的解决方案?

解释查询: 在此处输入图像描述

显示创建:

CREATE TABLE `candles` (
  `time` int(10) unsigned NOT NULL,
  `open` float unsigned NOT NULL,
  `high` float unsigned NOT NULL,
  `low` float unsigned NOT NULL,
  `close` float unsigned NOT NULL,
  `vb` int(10) unsigned NOT NULL,
  `vs` int(10) unsigned NOT NULL,
  `trades` int(10) unsigned NOT NULL,
  PRIMARY KEY (`time`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

如果数据库版本为8.0 ,则可以使用递归公用表表达式,例如

WITH RECURSIVE cte AS 
(
  SELECT 1 AS n
  UNION ALL
  SELECT n + 1 AS value
    FROM cte
   WHERE cte.n < (SELECT MAX(time) FROM tab )
)
SELECT n AS gaps
  FROM cte
  LEFT JOIN tab
    ON n=time
 WHERE cte.n > (SELECT MIN(time) FROM tab ) 
   AND time IS NULL

演示

在 MySQL 5.7 中,这是一个用户变量可能有用的用例:

select max(time)
from (
    select t.time, @rn := @rn + 1 as rn 
    from (select time from mytable order by time) t
    cross join (select @rn := 0) r
) t
group by time - rn

这将问题作为一个间隙和孤岛问题来解决。 这个想法是识别时间增量没有间隙(岛屿)的记录组。 为此,我们为每一行分配一个递增的 id,按时间排序; 每当time和自动增量之间的差异发生变化时,您就会知道存在差距。

对于 mysql 8,您可以使用 LEAD():

select time from (
    select time, lead(time, 1) over (order by time) next_time
    from `table`
) t
where time+1 != next_time

在早期版本中,我可能会这样做:

select prev_time as time from (
    select @prev_time+0 as prev_time,if(@prev_time:=time,time,time) as time
    from (select @prev_time:=null) initvars
    cross join (select time from `table` order by time) t
) t
where time != prev_time+1

两者都不会包括您的原始查询所包含的最长时间。

我认为 group by 需要将其视为严格的差距和岛屿问题,因为有那么多记录,代价太大了。

小提琴

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM