Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Metode menemukan kesenjangan dalam data deret waktu di MySQL?

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


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySQL INSERT SELECT - Duplikat baris

  2. Python Pandas - Menggunakan to_sql untuk menulis bingkai data besar dalam potongan

  3. perbarui data di div

  4. Haruskah saya menggunakan koneksi persisten mysql?

  5. Perbedaan antara mysql_fetch_array dan mysql_fetch_row?