Postgres SQL для заполнения пробелов временных рядов для нескольких групп - PullRequest
0 голосов
/ 30 мая 2020

У меня есть одна такая таблица, которая охватывает 2 дня сбора данных:

   class   timestamp              count

   2       2020-05-20 03:10:00    4
   1       2020-05-21 07:45:00    2
   6       2020-05-20 09:20:00    1
   2       2020-05-21 11:30:00    1
   5       2020-05-21 21:50:00    3
   1       2020-05-21 07:45:00    5
   5       2020-05-20 14:55:00    2

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

С каждым уникальным классом нужно обращаться таким образом - группируйте по классам, заполняйте недостающие 5 минут по порядку, суммируйте любые подсчеты с точно такой же меткой времени в этой группе, упорядочивая по метке времени. Общий результат должен быть упорядочен по возрастанию класса.

Спасибо за любую помощь.

Ответы [ 2 ]

0 голосов
/ 30 мая 2020

Предположим, ваше определение таблицы:

create table events(
    class       int,
    ts          timestamp,
    cnt         int
);

Пример запроса, сделайте все пошагово:

with time_range as (
    select timestamp '2020-05-20 00:00:00' as start_time,   -- current_timestamp - interval '2 day'
           timestamp '2020-05-22 00:00:00' as end_time      -- current_timestamp
),
interested_events as (
    select e.class, e.ts, e.cnt
    from events e
    inner join time_range tr
        on (e.ts >= tr.start_time and e.ts < tr.end_time)
),
classes_having_events as (
    select distinct class
    from interested_events
),
periods as (
    select ts as period_start, ts + interval '5 minute' as period_end
    from generate_series(
        (select start_time from time_range), 
        (select end_time from time_range) - interval '1 second',  
        interval '5 minute') ts 
)
select
    c.class, 
    p.period_start ts,
    (select coalesce(sum(cnt), 0) 
    from interested_events e
    where e.class = c.class
      and e.ts >= p.period_start
      and e.ts < p.period_end) as cnt
from classes_having_events as c
cross join periods as p
order by 2, 1;

В time_range определите временной интервал для событий ведьмы быть проанализировано.

В заинтересованных_событиях события выбираются на основе предыдущего определенного временного интервала ( диапазон_времени - время_пуска включительно, время_кончания исключено).

В * Создано 1017 * classes_having_events набор классов. Включены все классы с хотя бы одним событием в выбранном временном интервале.

В периодах созданы 5-минутные периоды.

Наконец, мы перекрестно объединяем набор классов с периодами и для каждой комбинации класса и периода вычислить количество событий.

0 голосов
/ 30 мая 2020

Postgres делает это особенно простым с помощью left join. Следующее имеет одну строку на метку времени:

select gs.ts, coalesce(sum(t.count), 0)
from generate_series('2020-05-20 00:00:00'::timestamp, '2020-05-21 23:55:00'::timestamp, interval '5 minute') gs(ts) left join
     t
     on t.timestamp = gs.ts
group by gs.ts;

Если вы хотите, чтобы это было разбито по классам (я действительно не могу сказать, что вы намереваетесь, основываясь на формулировке вопроса), тогда используйте cross join для генерации строк и left join и агрегирования:

select c.class, gs.ts, coalesce(sum(t.count), 0)
from generate_series('2020-05-20 00:00:00'::timestamp, '2020-05-21 23:55:00'::timestamp, interval '5 minute') gs(ts) cross join
     (select distinct class from t) c left join
     t
     on t.timestamp = gs.ts
group by c.class, gs.ts;

Мне приходит в голову, что метки времени могут быть неточными в ваших данных. В таком случае используйте неравенства для join:

     on t.timestamp >= gs.ts and
        t.timestamp < gs.ts + interval '5 minute'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...