Szybki i brudny sposób:http://sqlfiddle.com/#!1/bd2f6/21 Nazwałem moją kolumnę tstamp
zamiast Twojego 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
Krótkie wyjaśnienie:
- Oblicz minimalny i maksymalny znacznik czasu
- Generuj 15-minutowe odstępy między minimum a maksimum
- Wyniki łączenia krzyżowego z unikalnymi wartościami czasu trwania
- Left join oryginalne dane (left join jest ważne, ponieważ zachowa wszystkie możliwe kombinacje na wyjściu i będzie
null
gdzie czas trwania nie istnieje dla danego przedziału. - Zagregowane dane.
count(null)=0
W przypadku, gdy masz więcej tabel i algorytm powinien być zastosowany do ich unii. Załóżmy, że mamy trzy tabele tmp1, tmp2, tmp3
wszystkie z kolumnami tstamp
i duration
. Możemy rozszerzyć poprzednie rozwiązanie:
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
Naprawdę powinieneś znać with
klauzula w PostgreSQL. Jest to nieoceniona koncepcja dla każdej analizy danych w PostgreSQL.