Mysql
 sql >> база данни >  >> RDS >> Mysql

Метод за намиране на пропуски в данните от времеви серии в MySQL?

Като начало, нека обобщим броя на записите по час във вашата таблица.

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)

Сега, ако регистрирате нещо на всеки шест минути (десет пъти на час), всичките ви стойности на извадката трябва да са десет. Този израз:CAST(DATE_FORMAT(entry_time,'%Y-%m-%d %k:00:00') AS DATETIME) изглежда космат, но просто съкращава вашите времеви марки до часа, в който се появяват, като нулира минутата и секундата.

Това е сравнително ефективно и ще ви помогне да започнете. Много е ефективно, ако можете да поставите индекс във вашата колона entry_time и да ограничите заявката си до, да речем, вчерашни проби, както е показано тук.

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)

Но не е много добре за откриване на цели часове, които минават с липсващи проби. Освен това е малко чувствителен към трептене във вашата семплиране. Това означава, че ако вашата проба от най-горния час понякога е с половин секунда по-рано (10:59:30), а понякога и с половин секунда закъснение (11:00:30), вашите почасови обобщения ще бъдат изключени. Така че това обобщение за час (или обобщение за деня, или обобщение за минути и т.н.) не е бронирано.

Имате нужда от заявка за самостоятелно присъединяване, за да получите нещата перфектно; това е малко повече като топка за коса и не е толкова ефективно.

Нека започнем, като си създадем виртуална таблица (подзаявка) като тази с номерирани образци. (Това е болка в MySQL; някои други скъпи СУБД го правят по-лесно. Няма значение.)

  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

Тази малка виртуална таблица дава entry_num, entry_time, стойност.

Следващата стъпка, ние го присъединяваме към себе си.

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)

Това подрежда следващите две таблици една към друга, компенсирани с един запис, управляван от клаузата ON на JOIN.

Накрая избираме стойностите от тази таблица с interval по-голям от вашия праг и има времената на пробите точно преди липсващите.

Цялата заявка за самостоятелно присъединяване е следната. Казах ти, че е кълбо.

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)

Ако трябва да направите това в производството на голяма таблица, може да искате да го направите за подмножество от вашите данни. Например, можете да го правите всеки ден за пробите от предходните два дни. Това би било прилично ефективно и също така би се уверило, че няма да пропуснете липсващи проби точно в полунощ. За да направите това, вашите малки виртуални таблици с номера на редове ще изглеждат така.

  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 сървър

  2. Как да премахнете акцентите в MySQL?

  3. ИЗТРИВАНЕ на всички дублиращи се теми с няколко условия

  4. MySQL - Entity :Стойността за колона 'IsPrimaryKey' в таблица 'TableDetails' е DBNull

  5. получите по географска ширина и дължина в laravel 5 с други съединения