假设我们有一个包含两列的数据库表,entry_time 和 value。 entry_time 是时间戳,而 value 可以是任何其他数据类型。记录相对一致,大约以 x 分钟为间隔输入。然而,对于许多 x 的时间,可能不会进行输入,从而在数据中产生“间隙”。
就效率而言,通过查询找到至少时间为 Y(新旧)的差距的最佳方法是什么?
最佳答案
首先,让我们在您的表格中按小时汇总条目数。
SELECT CAST(DATE_FORMAT(entry_time,'%Y-%m-%d %k:00:00') AS DATETIME) hour,
COUNT(*) samplecount
FROM table
GROUP BY CAST(DATE_FORMAT(entry_time,'%Y-%m-%d %k:00:00') AS DATETIME)
现在,如果您每六分钟记录一次(每小时十次),您所有的 samplecount 值都应该是十。这个表达式:CAST(DATE_FORMAT(entry_time,'%Y-%m-%d %k:00:00') AS DATETIME)
看起来毛茸茸的,但它只是将你的时间戳截断到它们所在的时间通过将分和秒归零来发生。
这是相当有效的,可以帮助您入门。如果您可以在您的 entry_time 列上放置一个索引并将您的查询限制为比方说昨天的示例,如此处所示,将会非常有效。
SELECT CAST(DATE_FORMAT(entry_time,'%Y-%m-%d %k:00:00') AS DATETIME) hour,
COUNT(*) samplecount
FROM table
WHERE entry_time >= CURRENT_DATE - INTERVAL 1 DAY
AND entry_time < CURRENT_DATE
GROUP BY CAST(DATE_FORMAT(entry_time,'%Y-%m-%d %k:00:00') AS DATETIME)
但它不太擅长检测丢失样本的整个时间。它对采样中的抖动也有点敏感。也就是说,如果您的每小时最高样本有时早半秒 (10:59:30),有时晚半秒 (11:00:30),您的每小时摘要计数将会关闭。因此,这个小时摘要(或日摘要、分钟摘要等)并不是万无一失的。
您需要一个自连接查询来获得完美的结果;这有点像毛球,而且效率不高。
让我们首先为自己创建一个带有编号样本的虚拟表(子查询)。 (这在 MySQL 中是一个痛苦;其他一些昂贵的 DBMS 使它变得更容易。没关系。)
SELECT @sample:=@sample+1 AS entry_num, c.entry_time, c.value
FROM (
SELECT entry_time, value
FROM table
ORDER BY entry_time
) C,
(SELECT @sample:=0) s
这个小虚拟表给出了 entry_num、entry_time、值。
下一步,我们将其加入自身。
SELECT one.entry_num, one.entry_time, one.value,
TIMEDIFF(two.value, one.value) interval
FROM (
/* virtual table */
) ONE
JOIN (
/* same virtual table */
) TWO ON (TWO.entry_num - 1 = ONE.entry_num)
这会将下一个表排成一行,彼此偏移一个条目,由 JOIN 的 ON 子句控制。
最后,我们从该表中选择interval
大于您的阈值的值,并且在缺失值之前有样本的时间。
整个自连接查询是这样的。我告诉过你这是一个毛团。
SELECT one.entry_num, one.entry_time, one.value,
TIMEDIFF(two.value, one.value) interval
FROM (
SELECT @sample:=@sample+1 AS entry_num, c.entry_time, c.value
FROM (
SELECT entry_time, value
FROM table
ORDER BY entry_time
) C,
(SELECT @sample:=0) s
) ONE
JOIN (
SELECT @sample2:=@sample2+1 AS entry_num, c.entry_time, c.value
FROM (
SELECT entry_time, value
FROM table
ORDER BY entry_time
) C,
(SELECT @sample2:=0) s
) TWO ON (TWO.entry_num - 1 = ONE.entry_num)
如果您必须在大型表的生产环境中执行此操作,您可能希望对您的数据子集执行此操作。例如,您可以每天对前两天的样本执行此操作。这将非常有效,并且还可以确保您不会在午夜时分错过任何丢失的样本。为此,您的小行编号虚拟表将如下所示。
SELECT @sample:=@sample+1 AS entry_num, c.entry_time, c.value
FROM (
SELECT entry_time, value
FROM table
ORDER BY entry_time
WHERE entry_time >= CURRENT_DATE - INTERVAL 2 DAY
AND entry_time < CURRENT_DATE /*yesterday but not today*/
) C,
(SELECT @sample:=0) s
关于mysql - 在MySQL中查找时间序列数据差距的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41539471/