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

SQL - Намерете всички времена на прекъсване и дължините на престой от MySQL данни (набор от редове с времеви печати и съобщения за състоянието)

Ето един подход.

Започнете, като подредите редовете за състоянието по времева марка (вграден изглед с псевдоним като s ). След това използвайте потребителски променливи на MySQL, за да запазите стойностите от предишните редове, докато обработвате всеки ред.

Това, което наистина търсим, е статус „нагоре“, който непосредствено следва последователност от статус „надолу“. И когато намерим този ред със статус „нагоре“, това, от което наистина се нуждаем, е най-ранната времева марка от предходната серия от статус „надолу“.

Така че, нещо подобно ще работи:

SELECT d.start_down
     , d.ended_down
  FROM (SELECT @i := @i + 1 AS i
             , @start := IF(s.status = 'down' AND (@status = 'up' OR @i = 1), s.time, @start) AS start_down
             , @ended := IF(s.status = 'up' AND @status = 'down', s.time, NULL) AS ended_down
             , @status := s.status
         FROM (SELECT t.time
                    , t.status
                 FROM mydata t
                WHERE t.status IN ('up','down')
                ORDER BY t.time ASC, t.status ASC
              ) s
         JOIN (SELECT @i := 0, @status := 'up', @ended := NULL, @start := NULL) i
      ) d
WHERE d.start_down IS NOT NULL
  AND d.ended_down IS NOT NULL

Това работи за конкретния набор от данни, който показвате.

Това, което това не обработва (това, което не връща), е период „надолу“, който все още не е приключил, тоест поредица от състояние „надолу“ без последващо състояние „нагоре“.

За да избегнете операция за сортиране на файлове за връщане на редовете в ред, ще искате покриващ индекс на (time,status) . Тази заявка ще генерира временна (MyISAM) таблица, за да материализира вградения изглед с псевдоним като d .

ЗАБЕЛЕЖКА: За да разберете какво прави тази заявка, отлепете тази най-външна заявка и изпълнете само заявката за вградения изглед с псевдоним като d (можете да добавите s.time към списъка за избор.)

Тази заявка получава всеки ред със състояние "нагоре" или "надолу". "Трикът" е, че присвоява както "начало", така и "край" (маркиране на период на спад) само на редовете, които завършват "надолу" период. (Тоест, първият ред със състояние „нагоре“ следва редове със състояние „надолу“.) Тук се извършва истинската работа, най-външната заявка просто филтрира всички „допълнителни“ редове в този набор от резултати (че ние няма нужда.)

SELECT @i := @i + 1 AS i
     , @start := IF(s.status = 'down' AND (@status = 'up' OR @i = 1), s.time, @start) AS start_down
     , @ended := IF(s.status = 'up' AND @status = 'down', s.time, NULL) AS ended_down
     , @status := s.status
     , s.time
  FROM (SELECT t.time
             , t.status
          FROM mydata t
         WHERE t.status IN ('up','down')
         ORDER BY t.time ASC, t.status ASC
       ) s
  JOIN (SELECT @i := 0, @status := 'up', @ended := NULL, @start := NULL) i

Целта на вградения изглед с псевдоним като s е да получим редовете, подредени по стойност на времеви печат, така че да можем да ги обработваме последователно. Вграденият изглед с псевдоним като i е само там, за да можем да инициализираме някои потребителски променливи в началото на заявката.

Ако работихме на Oracle или SQL Server, бихме могли да използваме "аналитични функции" или "функции за класиране" (както се наричат ​​съответно.) MySQL не предоставя нищо подобно, така че трябва да "развием нашите собствени ".



  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. Highcharts многоредови графики

  3. Функция Jaro-winkler:защо един и същ резултат съвпада с много сходни и много различни думи?

  4. Кеширане на подготвени изявления за PDO

  5. Не може да се получи пружинно зареждане за автоматично създаване на схема на база данни