Untuk memulainya, mari kita rangkum jumlah entri per jam di tabel Anda.
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)
Sekarang, jika Anda mencatat sesuatu setiap enam menit (sepuluh kali satu jam), semua nilai jumlah sampel Anda harus sepuluh. Ekspresi ini:CAST(DATE_FORMAT(entry_time,'%Y-%m-%d %k:00:00') AS DATETIME)
terlihat berbulu tetapi hanya memotong stempel waktu Anda ke jam di mana mereka muncul dengan memusatkan perhatian pada menit dan detik.
Ini cukup efisien, dan akan membantu Anda memulai. Ini sangat efisien jika Anda dapat menempatkan indeks pada kolom entry_time Anda dan membatasi kueri Anda, katakanlah, sampel kemarin seperti yang ditunjukkan di sini.
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)
Tapi itu tidak terlalu bagus dalam mendeteksi seluruh jam yang berlalu dengan sampel yang hilang. Ini juga sedikit sensitif terhadap jitter dalam pengambilan sampel Anda. Artinya, jika sampel jam kerja teratas Anda terkadang setengah detik lebih awal (10:59:30) dan terkadang terlambat setengah detik (11:00:30), penghitungan ringkasan per jam Anda akan dinonaktifkan. Jadi, ringkasan jam ini (atau ringkasan hari, atau ringkasan menit, dll) tidak antipeluru.
Anda memerlukan kueri self-join untuk mendapatkan barang dengan benar; itu sedikit lebih seperti bola rambut dan tidak seefisien itu.
Mari kita mulai dengan membuat tabel virtual (subquery) seperti ini dengan sampel bernomor. (Ini menyebalkan di MySQL; beberapa DBMS mahal lainnya membuatnya lebih mudah. Tidak masalah.)
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
Tabel virtual kecil ini memberikan entry_num, entry_time, nilai.
Langkah selanjutnya, kita gabungkan dengan dirinya sendiri.
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)
Ini menyusun tabel di depan dua sama lain diimbangi oleh satu entri, diatur oleh klausa ON dari JOIN.
Akhirnya kami memilih nilai dari tabel ini dengan interval
lebih besar dari ambang batas Anda, dan ada waktu sampel tepat sebelum yang hilang.
Permintaan bergabung sendiri secara keseluruhan adalah ini. Sudah kubilang itu bola rambut.
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)
Jika Anda harus melakukan ini dalam produksi pada tabel besar, Anda mungkin ingin melakukannya untuk subset data Anda. Misalnya, Anda dapat melakukannya setiap hari untuk sampel dua hari sebelumnya. Ini akan cukup efisien, dan juga akan memastikan Anda tidak mengabaikan sampel yang hilang tepat di tengah malam. Untuk melakukan ini, tabel virtual bernomor baris kecil Anda akan terlihat seperti ini.
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