sql >> Database teknologi >  >> RDS >> Mysql

Metode til at finde huller i tidsseriedata i MySQL?

Til at starte med, lad os opsummere antallet af tilmeldinger pr. time i din tabel.

SELECT CAST(DATE_FORMAT(entry_time,'%Y-%m-%d %k:00:00') AS DATETIME) time, COUNT(*) samplecount FROM table GROUP BY CAST(DATE_FORMAT(entry_time, '%Y-%m-%d %k:00:00') SOM DATOTIME) 

Nu, hvis du logger noget hvert sjette minut (ti gange i timen), skal alle dine samplecount-værdier være ti. Dette udtryk:CAST(DATE_FORMAT(entry_time,'%Y-%m-%d %k:00:00') AS DATETIME) ser behåret ud, men det afkorter simpelthen dine tidsstempler til den time, hvor de forekommer, ved at nulstille minut og sekund.

Dette er rimeligt effektivt og vil få dig i gang. Det er meget effektivt, hvis du kan sætte et indeks på din entry_time-kolonne og begrænse din forespørgsel til, lad os sige, gårsdagens eksempler som vist her.

SELECT CAST(DATE_FORMAT(entry_time,'%Y-%m-%d %k:00:00') AS DATETIME) time, COUNT(*) samplecount FROM table WHERE entry_time>=CURRENT_DATE - INTERVAL 1 DAG OG indgangstidspunkt  

Men den er ikke særlig god til at opdage hele timer, der går med manglende prøver. Det er også lidt følsomt over for jitter i din sampling. Det vil sige, at hvis din top-of-the-time-prøve nogle gange er et halvt sekund for tidligt (10:59:30) og nogle gange et halvt sekund forsinket (11:00:30), vil dine timeoversigtstællinger være slået fra. Så denne timeopsummering (eller dagsoversigt, eller minutoversigt osv.) er ikke skudsikker.

Du har brug for en selvtilmeldingsforespørgsel for at få tingene helt rigtige; det er lidt mere en hårbold og ikke nær så effektiv.

Lad os starte med at skabe os en virtuel tabel (underforespørgsel) som denne med nummererede eksempler. (Dette er en smerte i MySQL; nogle andre dyre DBMS'er gør det lettere. Uanset hvad.)

 VÆLG @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 

Denne lille virtuelle tabel giver entry_num, entry_time, value.

Næste trin forbinder vi det med sig selv.

VÆLG én.indgang_nummer, én.indgang_tid, én.værdi, TIMEDIFF(to.værdi, én.værdi) interval FRA ( /* virtuel tabel */ ) ONE JOIN ( /* samme virtuelle tabel */ ) TO TIL (TWO.entry_num - 1 =ONE.entry_num)

Dette stiller de næste to tabeller op ad hinanden forskudt af en enkelt indtastning, styret af ON-klausulen i JOIN.

Til sidst vælger vi værdierne fra denne tabel med et interval større end din tærskel, og der er tidspunkterne for prøverne lige før de manglende.

Den overordnede selvforespørgsel er dette. Jeg fortalte dig, at det var en hårbold.

VÆLG one.entry_num, one.entry_time, one.value, TIMEDIFF(to.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) 

Hvis du skal gøre dette i produktionen på en stor tabel, vil du måske gøre det for en delmængde af dine data. For eksempel kan du gøre det hver dag for de foregående to dages prøver. Dette ville være anstændigt effektivt og ville også sikre, at du ikke overså eventuelle manglende prøver lige ved midnat. For at gøre dette ville dine små rækkenummererede virtuelle borde se sådan ud.

 VÆLG @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  


  1. MySQL-serverstartproblemer på Mavericks

  2. MySQL/Python -> Forkert syntaks for pladsholder i erklæringer?

  3. Implementering af failover i MS SQL Server 2017 Standard

  4. Transponering af et sql-resultat, så en kolonne går over i flere kolonner