SQL: Как построить временной ряд из нерегулярных данных, а затем вычислить скользящее среднее по нему - PullRequest
0 голосов
/ 19 февраля 2020

Я пытаюсь рассчитать скользящее среднее данных из отчетов об инцидентах. Точное количество, которое я ищу, - это среднее время разрешения за 30 дней ( mttr ), которое означает среднее время, необходимое для разрешения инцидентов за последние 30 дней.

Моя таблица инцидентов выглядит примерно так:

| incident_id | start_datetime        | end_datetime          |
|-------------|-----------------------|-----------------------|
| 1           | '2020-02-01T10:13:00' | '2020-02-01T10:59:33' |
| 2           | '2020-02-01T17:55:13' | '2020-02-02T00:35:28' |
| 3           | '2020-02-03T13:33:01' | '2020-02-03T15:54:01' |

Я хочу что-то вроде этого (цифры составлены, поэтому не пытайтесь на самом деле рассчитать - просто обратите внимание, что интервалы даты и времени - каждый час):

| datetime              | mttr_last30days_in_hours |
|-----------------------|--------------------------|
| '2020-02-01T10:00:00' | 5.7                      |
| '2020-02-01T11:00:00' | 5.6                      |
| '2020-02-02T12:00:00' | 5.8                      |

Я могу очень легко рассчитать mttr за последние 30 дней, если я делаю это только для одного момента времени:

SELECT avg(end_datetime - start_datetime) mttr_last30days_in_hours
FROM incidents
WHERE datetime_diff(current_datetime(), start_datetime, DAY) <= 30 

Проблема в том, что это просто дает мне ОДИН номер. Как создать временной ряд, охватывающий диапазон, скажем, start_datetime первого инцидента (min(start_datetime)) до текущего времени, а затем получить скользящее среднее значение за 30 дней с равномерно распределенными часовыми интервалами (как в приведенной выше таблице примеров)?

1 Ответ

1 голос
/ 19 февраля 2020

Если у вас есть уникальное поле в вашей таблице, вы можете попробовать сделать это:

WITH

t_filter AS(
  SELECT 
     *
  FROM
    incidents 
  WHERE datetime_diff(current_datetime(), start_datetime, DAY) <= 30 
),

t_dates AS (
  SELECT
    unique_key,
    GENERATE_DATE_ARRAY(DATE(start_datetime), CURRENT_DATE(), INTERVAL 1 DAY) AS date_array
  FROM
    t_filter
),

t_hour AS (
  SELECT *
  FROM
  UNNEST(["00:00:00",
    "01:00:00",
    "02:00:00",
    "03:00:00",
    "04:00:00",
    "05:00:00",
    "06:00:00",
    "07:00:00",
    "08:00:00",
    "09:00:00",
    "10:00:00",
    "11:00:00",
    "12:00:00",
    "13:00:00",
    "14:00:00",
    "15:00:00",
    "16:00:00",
    "17:00:00",
    "18:00:00",
    "19:00:00",
    "20:00:00",
    "21:00:00",
    "22:00:00",
    "23:00:00"]) h 
),

sequence AS(
  SELECT
    unique_key,
    CONCAT(CAST(arr AS string),"T", h) date_hour
  FROM
    t_dates,
    UNNEST(date_array) arr,
    t_hour
)

SELECT
  date_hour,
  AVG(end_datetime - start_datetime)
FROM
  sequence
LEFT JOIN
  t_filter
ON
incidents.unique_key = sequence.unique_key
GROUP BY
  date_hour

Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...