Laten we om te beginnen het aantal inschrijvingen per uur samenvatten in uw tabel.
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)
Als u nu elke zes minuten (tien keer per uur) iets logt, zouden al uw samplecount-waarden tien moeten zijn. Deze uitdrukking:CAST(DATE_FORMAT(entry_time,'%Y-%m-%d %k:00:00') AS DATETIME)
ziet er harig uit, maar het kapt je tijdstempels eenvoudig af tot het uur waarin ze voorkomen door de minuut en seconde op nul te zetten.
Dit is redelijk efficiënt en helpt u op weg. Het is erg efficiënt als u een index op uw entry_time-kolom kunt plaatsen en uw zoekopdracht kunt beperken tot, laten we zeggen, voorbeelden van gisteren, zoals hier weergegeven.
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)
Maar het is niet zo goed in het detecteren van hele uren die verstrijken met ontbrekende monsters. Het is ook een beetje gevoelig voor jitter in uw bemonstering. Dat wil zeggen, als uw steekproef op het hoogste uur soms een halve seconde te vroeg is (10:59:30) en soms een halve seconde te laat (11:00:30), zijn uw uuroverzichten uitgeschakeld. Dus dit uuroverzicht (of dagoverzicht, of minutenoverzicht, enz.) is niet kogelvrij.
Je hebt een self-join-query nodig om dingen helemaal goed te krijgen; het is een beetje meer een haarbal en lang niet zo efficiënt.
Laten we beginnen met het maken van een virtuele tabel (subquery) zoals deze voor onszelf met genummerde voorbeelden. (Dit is lastig in MySQL; sommige andere dure DBMS'en maken het gemakkelijker. Maakt niet uit.)
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
Deze kleine virtuele tabel geeft entry_num, entry_time, waarde.
De volgende stap voegen we toe aan zichzelf.
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)
Dit plaatst de tabellen naast elkaar, verschoven door een enkele invoer, geregeld door de ON-clausule van de JOIN.
Tenslotte kiezen we de waarden uit deze tabel met een interval
groter is dan uw drempel, en er zijn de tijden van de monsters vlak voor de ontbrekende.
De algemene zelf-join-query is dit. Ik zei toch dat het een haarbal was.
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)
Als u dit in productie op een grote tafel moet doen, wilt u dit misschien doen voor een subset van uw gegevens. U kunt dit bijvoorbeeld elke dag doen voor de monsters van de afgelopen twee dagen. Dit zou behoorlijk efficiënt zijn, en zou er ook voor zorgen dat je om middernacht geen ontbrekende monsters over het hoofd zag. Om dit te doen zouden uw kleine rijgenummerde virtuele tafels er als volgt uitzien.
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