Бърз и мръсен начин:http://sqlfiddle.com/#!1/bd2f6/21 Нарекох колоната си tstamp
вместо вашия timestamp
with t as (
select
generate_series(mitstamp,matstamp,'15 minutes') as int,
duration
from
(select min(tstamp) mitstamp, max(tstamp) as matstamp from tmp) a,
(select duration from tmp group by duration) b
)
select
int as timestampwindowstart,
t.duration,
count(tmp.duration)
from
t
left join tmp on
(tmp.tstamp >= t.int and
tmp.tstamp < (t.int + interval '15 minutes') and
t.duration = tmp.duration)
group by
int,
t.duration
order by
int,
t.duration
Кратко обяснение:
- Изчисляване на минимално и максимално време
- Генерирайте интервали от 15 минути между минимума и максимума
- Резултати от кръстосано свързване с уникални стойности на продължителност
- Оригинални данни за ляво съединение (лявото съединение е важно, защото това ще запази всички възможни комбинации в изхода и ще има
null
където продължителността не съществува за даден интервал. - Обобщени данни.
count(null)=0
В случай, че имате повече таблици и алгоритъмът трябва да се приложи върху тяхното обединение. Да предположим, че имаме три таблици tmp1, tmp2, tmp3
всички с колони tstamp
и duration
. Можем да разширим предишното решение:
with
tmpout as (
select * from tmp1 union all
select * from tmp2 union all
select * from tmp3
)
,t as (
select
generate_series(mitstamp,matstamp,'15 minutes') as int,
duration
from
(select min(tstamp) mitstamp, max(tstamp) as matstamp from tmpout) a,
(select duration from tmpout group by duration) b
)
select
int as timestampwindowstart,
t.duration,
count(tmp.duration)
from
t
left join tmpout on
(tmp.tstamp >= t.int and
tmp.tstamp < (t.int + interval '15 minutes') and
t.duration = tmp.duration)
group by
int,
t.duration
order by
int,
t.duration
Наистина трябва да знаете with
клауза в PostgreSQL. Това е безценна концепция за всеки анализ на данни в PostgreSQL.