Pro začátek shrňme počet záznamů podle hodin ve vaší tabulce.
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)
Nyní, pokud něco zaznamenáte každých šest minut (desetkrát za hodinu), všechny vaše hodnoty samplecount by měly být deset. Tento výraz:CAST(DATE_FORMAT(entry_time,'%Y-%m-%d %k:00:00') AS DATETIME)
vypadá chlupatě, ale jednoduše zkrátí vaše časová razítka na hodinu, ve které se vyskytují, vynulováním minuty a sekundy.
To je přiměřeně efektivní a pomůže vám to začít. Je velmi efektivní, pokud můžete umístit index do sloupce entry_time a omezit svůj dotaz na, řekněme, včerejší vzorky, jak je uvedeno zde.
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)
Ale není to moc dobré na odhalování celých hodin, které uplynou s chybějícími vzorky. Je také trochu citlivý na chvění při vzorkování. To znamená, že pokud je váš vzorek nejvyšší hodiny někdy o půl sekundy dříve (10:59:30) a někdy o půl sekundy později (11:00:30), vaše hodinové souhrnné počty budou vypnuté. Takže tento hodinový souhrn (nebo shrnutí dne, nebo minutový souhrn atd.) není neprůstřelný.
Chcete-li, aby byly věci dokonale správné, potřebujete dotaz na vlastní spojení; je to trochu více chlupáče a není zdaleka tak účinné.
Začněme tím, že si vytvoříme virtuální tabulku (poddotaz) takto s očíslovanými vzorky. (To je problém MySQL; některé jiné drahé DBMS to usnadňují. Nevadí.)
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
Tato malá virtuální tabulka poskytuje entry_num, entry_time, value.
V dalším kroku jej připojíme k sobě.
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)
Tím se seřadí další dvě tabulky navzájem posunuté o jeden záznam, který se řídí klauzulí ON v JOIN.
Nakonec vybereme hodnoty z této tabulky s interval
větší než váš práh a před chybějícími jsou časy vzorků.
Celkový dotaz na samostatné připojení je tento. Řekl jsem ti, že to byla koule na vlasy.
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)
Pokud to musíte udělat v produkci na velké tabulce, možná to budete chtít udělat pro podmnožinu vašich dat. Můžete to například udělat každý den pro vzorky z předchozích dvou dnů. To by bylo slušně efektivní a také by to zajistilo, že hned o půlnoci nepřehlédnete žádné chybějící vzorky. Chcete-li to provést, vaše malé virtuální stoly s čísly řádků by vypadaly takto.
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