Manière rapide et sale :http://sqlfiddle.com/#!1/bd2f6/21 J'ai nommé ma colonne tstamp
au lieu de votre 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
Brève explication :
- Calculer l'horodatage minimum et maximum
- Générer des intervalles de 15 minutes entre le minimum et le maximum
- Résultats de jointure croisée avec des valeurs de durée uniques
- Joindre à gauche les données d'origine (la jointure à gauche est importante, car cela conservera toutes les combinaisons possibles dans la sortie et il y aura
null
où la durée n'existe pas pour un intervalle donné. - Données agrégées.
count(null)=0
Dans le cas où vous avez plus de tables et l'algorithme doit être appliqué sur leur union. Supposons que nous ayons trois tables tmp1, tmp2, tmp3
le tout avec des colonnes tstamp
et duration
. Ensuite, nous pouvons étendre la solution précédente :
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
Vous devriez vraiment savoir with
clause dans PostgreSQL. C'est un concept inestimable pour toute analyse de données dans PostgreSQL.