Wessi
Wessi

Reputation: 1822

Postgresql: Average for each day in interval

I have table that is structured like this:

item_id    first_observed    last_observed    price
1          2016-10-21        2016-10-27       121
1          2016-10-28        2016-10-31       145
2          2016-10-22        2016-10-28       135
2          2016-10-29        2016-10-30       169

What I want is to get the average price for every day. I obviously cannot just group by first_observed or last_observed. Does Postgres offer a smart way of doing this?

The expected output would be like this:

date        avg(price)
2016-10-21  121
2016-10-22  128
2016-10-23  128
2016-10-24  128
2016-10-25  128
2016-10-26  128
2016-10-27  128
2016-10-28  140
2016-10-29  157
2016-10-30  157
2016-10-31  157

I could also be outputted like this (both are fine):

start       end         avg(price)
2016-10-21  2016-10-21  121
2016-10-22  2016-10-27  128
2016-10-28  2016-10-28  140
2016-10-29  2016-10-31  157

Upvotes: 1

Views: 1241

Answers (2)

S-Man
S-Man

Reputation: 23756

demo:db<>fiddle

generate_series allows you to expand date ranges:

First step:

SELECT 
    generate_series(first_observed, last_observed, interval '1 day')::date as observed, 
    AVG(price)::int as avg_price
FROM items
GROUP BY observed
ORDER BY observed
  1. expanding the date range
  2. grouping the dates for AVG aggregate

Second step

SELECT 
    MIN(observed) as start,
    MAX(observed) as end,
    avg_price
FROM (
    -- <first step as subquery>
)s
GROUP BY avg_price
ORDER BY start
  1. Grouping by avg_price to get the MIN/MAX date for it

Upvotes: 2

FXD
FXD

Reputation: 2060

WITH ObserveDates (ObserveDate) AS (
    SELECT * FROM generate_series((SELECT MIN(first_observed) FROM T), (SELECT MAX(last_observed) FROM T), '1 days')
)
SELECT ObserveDate, AVG(Price)
FROM ObserveDates
JOIN T ON ObserveDate BETWEEN first_observed AND last_observed
GROUP BY ObserveDate
ORDER BY ObserveDate

Upvotes: 2

Related Questions