Как рассчитать время между двумя чередующимися событиями в SQL - PullRequest
0 голосов
/ 28 сентября 2019

Я ищу способ получить общее время между двумя чередующимися событиями в MYSQL.

Я использую базу данных MYSQL для хранения событий, когда дверь открывается / закрывается.Я ищу способ визуализировать общее время, когда дверь была открыта каждый час.

Я использую datareportive для визуализации своих данных, в настоящее время я могу показать, сколько раз дверь открывалась каждый час по следующему запросу:

SELECT DATE_FORMAT(DATE_ADD(date, INTERVAL 30 MINUTE),'%Y-%m-%d %H:00:00') as hour,
COUNT(*) as num_rows 
FROM events 
GROUP BY hour;

База данных выглядит следующим образом:

ID  door                    Action  date

13  my unique door name!    Open    2019-09-09T09:01:12
14  my unique door name!    Close   2019-09-09T09:01:23
15  my unique door name!    Open    2019-09-09T09:01:30
16  my unique door name!    Close   2019-09-09T09:01:35
17  my unique door name!    Open    2019-09-09T09:01:37
18  my unique door name!    Close   2019-09-09T09:01:40
19  my unique door name!    Open    2019-09-09T09:01:50

Я ищу способ, которым запрос возвращает общее время открытия двери каждый час.

Есть одна большая загвоздка: иногда события Open / Close не чередуются правильно, например, отключение питания на датчике двери может привести к тому, что событие, указанное в базе данных, будет в два раза больше

SQLfiddle

1 Ответ

0 голосов
/ 28 сентября 2019

Трудно предложить что-то конкретное без http://sqlfiddle.com/ примера.поэтому я могу просто дать вам стратегию.

  1. создайте столбец INTEGER с 1 / 0 для представления Open / Close событий.
  2. Используйте SUM(action_int) OVER (см. Пример здесь Рассчитайте промежуточную сумму в MySQL ), чтобы вычислить промежуточную сумму открытий и закрытий, которая даст вам уникальный идентификатор для каждой полной комбинации.
  3. Самостоятельно объединить эти результаты на основе этого идентификатора, фильтруя правую сторону к Open, левую сторону к Close
  4. Суммируя разницу между close_date и open_date от предыдущего шага крассчитать общее время, когда дверь была открыта.

Это должно позаботиться о ваших сиротских Open событиях.Возможно, вам придется немного поиграться с потерянными событиями Close, чтобы исключить их из набора данных.

Вот sql для Postgres, я полагаю, что с небольшими изменениями вы можете заставить его работать на MySql:

WITH door_events AS (
  SELECT 
    id, 
    door, 
    action, 
    SUM(action) OVER(PARTITION BY door ORDER BY date) AS cycle_id,
    date
  FROM 
      events 
)
SELECT 
  door, 
  SUM(date_close - date_open) door_open 
FROM
(
  SELECT 
   id as open_id,
   door as door,
   date as date_open,
   cycle_id
  FROM 
    door_events
  WHERE action = 1
) AS o LEFT JOIN
(
  SELECT 
    id as close_id,
    door as door_close,
    date as date_close,
    cycle_id
   FROM 
    door_events
   WHERE action = 0
) AS c ON o.cycle_id = c.cycle_id
GROUP BY door

http://sqlfiddle.com/#!17/bafb1/19/0

...