sql >> Databasteknik >  >> RDS >> Mysql

Metod för att hitta luckor i tidsseriedata i MySQL?

Till att börja med, låt oss sammanfatta antalet anmälningar per timme i din tabell.

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)

Nu, om du loggar något var sjätte minut (tio gånger i timmen) bör alla dina samplecount-värden vara tio. Detta uttryck:CAST(DATE_FORMAT(entry_time,'%Y-%m-%d %k:00:00') AS DATETIME) ser hårig ut men den kortar helt enkelt dina tidsstämplar till den timme då de inträffar genom att nollställa minut och sekund.

Detta är rimligt effektivt och kommer att komma igång. Det är mycket effektivt om du kan sätta ett index på kolumnen entry_time och begränsa din fråga till, låt oss säga, gårdagens exempel som visas här.

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)

Men det är inte så bra på att upptäcka hela timmar som går med saknade prover. Det är också lite känsligt för jitter i din sampling. Det vill säga, om ditt toppexemplar ibland är en halv sekund för tidigt (10:59:30) och ibland en halv sekund för sent (11:00:30) kommer dina timsammanfattningar att vara avstängda. Så den här timmessammanfattningen (eller dagssammanfattning, eller minutsammanfattning, etc) är inte skottsäker.

Du behöver en självanslutningsfråga för att få saker helt rätt; det är lite mer av en hårboll och inte alls lika effektivt.

Låt oss börja med att skapa oss en virtuell tabell (underfråga) som denna med numrerade exempel. (Detta är jobbigt i MySQL; vissa andra dyra DBMS:er gör det lättare. Oavsett.)

  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

Denna lilla virtuella tabell ger entry_num, entry_time, value.

Nästa steg, vi förenar det med sig självt.

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)

Detta radar upp tabellerna nästa två varandra förskjutna av en enda post, styrd av ON-klausulen i JOIN.

Slutligen väljer vi värdena från denna tabell med ett interval större än din tröskel, och det finns tidpunkter för proverna precis före de saknade.

Den övergripande självanslutningsfrågan är denna. Jag sa att det var en hårboll.

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)

Om du måste göra detta i produktion på ett stort bord kanske du vill göra det för en delmängd av dina data. Du kan till exempel göra det varje dag för de föregående två dagarnas prover. Detta skulle vara hyfsat effektivt och skulle också se till att du inte förbisåg några saknade prover precis vid midnatt. För att göra detta skulle dina små radnumrerade virtuella bord se ut så här.

  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. SQL-fråga för att ta bort tabell i MySQL

  2. Hur konverterar man tidsstämpel till datetime i MySQL?

  3. Hur ansluter jag till en Oracle-databas i R?

  4. Skicka ett formulär med <input type =button>