Като начало, нека обобщим броя на записите по час във вашата таблица.
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)
Сега, ако регистрирате нещо на всеки шест минути (десет пъти на час), всичките ви стойности на извадката трябва да са десет. Този израз: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; някои други скъпи СУБД го правят по-лесно. Няма значение.)
SELECT @sample:[email protected]+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)
Това подрежда следващите две таблици една към друга, компенсирани с един запис, управляван от клаузата ON на JOIN.
Накрая избираме стойностите от тази таблица с interval
по-голям от вашия праг и има времената на пробите точно преди липсващите.
Цялата заявка за самостоятелно присъединяване е следната. Казах ти, че е кълбо.
SELECT one.entry_num, one.entry_time, one.value,
TIMEDIFF(two.value, one.value) interval
FROM (
SELECT @sample:[email protected]+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:[email protected]+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:[email protected]+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