Na początek podsumujmy liczbę wpisów w Twojej tabeli według godzin.
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)
Teraz, jeśli rejestrujesz coś co sześć minut (dziesięć razy na godzinę), wszystkie wartości liczby próbek powinny wynosić dziesięć. To wyrażenie:CAST(DATE_FORMAT(entry_time,'%Y-%m-%d %k:00:00') AS DATETIME)
wygląda na owłosioną, ale po prostu skraca znaczniki czasu do godziny, w której występują, wyzerowując minutę i sekundę.
Jest to dość wydajne i pozwoli Ci zacząć. Jest to bardzo wydajne, jeśli możesz umieścić indeks w kolumnie entry_time i ograniczyć zapytanie do, powiedzmy, wczorajszych próbek, jak pokazano tutaj.
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 nie jest zbyt dobry w wykrywaniu całych godzin, które mijają z brakującymi próbkami. Jest też trochę wrażliwy na jitter w twoim samplu. Oznacza to, że jeśli próbka z najwyższej półki jest czasami o pół sekundy za wcześnie (10:59:30), a czasami o pół sekundy za późno (11:00:30), liczniki godzinowego podsumowania będą wyłączone. Tak więc to podsumowanie godzinowe (lub podsumowanie dzienne lub podsumowanie minutowe itp.) Nie jest kuloodporne.
Potrzebujesz zapytania samozłączającego, aby wszystko było idealnie poprawne; jest trochę bardziej podobny do kuli włosowej i nie jest tak wydajny.
Zacznijmy od stworzenia sobie wirtualnej tabeli (podzapytania) z ponumerowanymi próbkami. (To jest kłopotliwe w MySQL; niektóre inne drogie DBMS-y ułatwiają to. Nieważne.)
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
Ta mała wirtualna tabela podaje numer_wpisu, czas_wpisu, wartość.
W następnym kroku łączymy go ze 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)
Spowoduje to wyrównanie kolejnych dwóch tabel z przesunięciem o jeden wpis, zgodnie z klauzulą ON JOIN.
Na koniec wybieramy wartości z tej tabeli z interval
większe niż próg, a czasy próbek znajdują się tuż przed brakującymi.
Oto kwerenda over all self join. Mówiłem ci, że to kula włosowa.
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)
Jeśli musisz to zrobić w środowisku produkcyjnym na dużej tabeli, możesz to zrobić dla podzbioru danych. Na przykład możesz to zrobić każdego dnia dla próbek z poprzednich dwóch dni. Byłoby to całkiem wydajne, a także zapewniłoby, że nie przeoczysz żadnych brakujących próbek tuż o północy. Aby to zrobić, Twoje małe wirtualne stoły o numerach rzędów będą wyglądać tak.
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