Niall McKenna
Niall McKenna

Reputation: 181

How to get an average value in a timescale in Postgres?

I have a lot of values in a postgres db that include a time value.

The database contains a record unit colors, something like this:

[
{
  id: 1234,
  unit: 2,
  color: "red",
  time: "Wed, 16 Dec 2020 21:45:30"
},
{
  id: 1235,
  unit: 2,
  color: "red",
  time: "Wed, 16 Dec 2020 21:47:30"
},{
  id: 1236,
  unit: 6,
  color: "blue",
  time: "Wed, 16 Dec 2020 21:48:30"
},
{
  id: 1237,
  unit: 6,
  color: "green",
  time: "Wed, 16 Dec 2020 21:49:30"
},
{
  id: 1237,
  unit: 6,
  color: "blue",
  time: "Wed, 16 Dec 2020 21:49:37"
},
]

I want to be able to query this list but in 10 minute averages, which should return the earliest record which contains the average.

For example in the 10 minute period of 21:40 - 21:50 I should only recieve the 2 unique units with the average value that they had within that time period.

The returned data should look something like this:

[
{
  id: 1234,
  unit: 2,
  color: "red",
  time: "Wed, 16 Dec 2020 21:45:30"
},
{
  id: 1236,
  unit: 6,
  color: "blue",
  time: "Wed, 16 Dec 2020 21:48:30"
},
]

What type of query should I be using to acheive soething like this?

Thanks

Upvotes: 0

Views: 375

Answers (1)

GMB
GMB

Reputation: 222672

You can use distinct on:

select distinct on (x.time_trunc, t.unit) t.*
from mytable t
cross join lateral (values (
    date_trunc('hour', time) 
        + extract(minute from time) / 10 * '10 minute'::interval)
) as x(time_trunc)
order by x.time_trunc, t.unit, t.time 

The trick is to truncate the timestamps to 10 minute. For this, we use date arithmetics; I moved the computation in a lateral join so there is no need to repeat the expression. Then, distinct on comes into play, to select the earlier record per timestamp bucket and per unit.

I don't see how the question relates to an average whatsoever.

Upvotes: 1

Related Questions