Sample Header Ad - 728x90

In PostgreSQL how to get the hourly minimum of a value using a window function?

0 votes
2 answers
58 views
Let's assume we have the following data with one temperature measurement per second. The span of data is several years so there is a considerable number of rows. It is measurement data from a field device. The table has other columns as well but they are not relevant to the question. | Time | Temperature_deg_in_C | | ---- | ------------------- | | 2024-11-01 00:00:00+00 | 20.1 | | 2024-11-01 00:00:01+00 | 21.2 | | 2024-11-01 00:00:02+00 | 21.6 | | 2024-11-01 00:00:03+00 | 20.2 | | ... | ... | | 2026-12-31 23:59:57+00 | 25.4 | | 2026-12-31 23:59:58+00 | 25.2 | | 2026-12-31 23:59:59+00 | 25.6 | I know that I can use a GROUP BY clause to get the averages over one hour windows between a specific start and end times like so:
SELECT to_char("time", 'YYYY-MM-DD HH'), AVG("Temperature_deg_in_C")
    FROM "measurements"
   WHERE "time" BETWEEN '2024-11-01' AND '2024-12-01'
GROUP BY to_char("time", 'YYYY-MM-DD HH')
However, this syntax feels like a hack, and it doesn't quite bend to e.g. 10 second or other more complex window frames (or partitions). Furthermore, I would like to know, specifically, how this is done correctly and performantly using the OVER, WINDOW, PARTITION BY, RANGE, ROWS and similar tools outlined in [PostgreSQL manual](https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS) . **UPDATE:** Window functions cannot be used to achieve this goal on Postgres, as they do not create "buckets" or "frames" in the way I thought they did. GROUP BY is the way to achieve this. The end goal is to find a solution where the window length and unit of measurement (minutes, hours, days), and the start and end time of the observing period are flexible but the query body itself stays the same. A parameterized query that is simple to understand, that is.
Asked by Antti Keskinen (3 rep)
Nov 28, 2024, 03:23 PM
Last activity: Nov 29, 2024, 05:52 AM