The*_*Dog 8 mysql database time
假设我们有一个包含两列的数据库表,entry_time和value.entry_time是时间戳,而value可以是任何其他数据类型.记录相对一致,以大约x分钟的间隔输入.然而,在许多时间内,可能不会进行输入,从而在数据中产生"间隙".
在效率方面,通过查询找到至少时间Y(新旧)的最佳方法是什么?
O. *_*nes 20
首先,让我们在表格中按小时汇总条目数.
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)
Run Code Online (Sandbox Code Playgroud)
现在,如果您每六分钟(每小时十次)记录一些内容,那么所有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)
Run Code Online (Sandbox Code Playgroud)
但是,在检测缺少样品的整个小时时,它并不是很好.它对采样中的抖动也有点敏感.也就是说,如果您的最高时间样本有时是早期的半秒(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
Run Code Online (Sandbox Code Playgroud)
这个小虚拟表给出了entry_num,entry_time,value.
下一步,我们加入它自己.
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)
Run Code Online (Sandbox Code Playgroud)
这将表格排列下来两个相互偏移的单个条目,由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)
Run Code Online (Sandbox Code Playgroud)
如果必须在大型表的生产中执行此操作,则可能需要为数据的子集执行此操作.例如,您可以每天对前两天的样本进行此操作.这将是相当有效的,并且还将确保您在午夜时不会忽略任何遗失的样本.要做到这一点,你的小小的rownumbered虚拟表将是这样的.
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
Run Code Online (Sandbox Code Playgroud)