Modo rapido e sporco:http://sqlfiddle.com/#!1/bd2f6/21 Ho chiamato la mia colonna tstamp
invece del tuo 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
Breve spiegazione:
- Calcola il timestamp minimo e massimo
- Genera intervalli di 15 minuti tra minimo e massimo
- Risultati di unione incrociata con valori di durata univoci
- Dati originali del join sinistro (il join sinistro è importante, perché questo manterrà tutte le possibili combinazioni in output e ci sarà
null
dove la durata non esiste per un determinato intervallo. - Dati aggregati.
count(null)=0
Nel caso in cui tu abbia più tabelle e l'algoritmo dovrebbe essere applicato sulla loro unione. Supponiamo di avere tre tabelle tmp1, tmp2, tmp3
tutti con colonne tstamp
e duration
. Possiamo estendere la soluzione precedente:
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
Dovresti davvero conoscere with
clausola in PostgreSQL. È un concetto prezioso per qualsiasi analisi dei dati in PostgreSQL.