Home > Back-end >  postgres, group by date, and bucketize per hour
postgres, group by date, and bucketize per hour

Time:02-01

I would like to create a result object that can be used with Grafana for a heatmap. In order to display the data correctly I need it the output to be like:

| date       | 00:00 | 01:00 | 02:00 | 03:00 | ...etc |
| 2023-01-01 | 1     | 2     | 0     | 1     | ...    |
| 2023-01-02 | 0     | 0     | 1     | 1     | ...    |
| 2023-01-03 | 4     | 0     | 2     | 0     | ...    |

my data table structure:

trades
-----
id
closed_at
asset

So far, I know that I need to use generate_series and use the interval function to return the hours, but I need my query to plot these hours as columns, but I've not been able to do that, as its getting a bit too advanced.

So far I have the following query:

SELECT 
    closed_at::DATE,
    COUNT(id)
FROM trades
GROUP BY closed_at
ORDER BY closed_at

It now shows the amount of rows grouped by the days, I want to further aggregate the data, so it outputs the count per hour, as shown above.

Thanks for your help!

CodePudding user response:

You can add more columns, now I only add 0:00 to 05:00.
filter usage: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-AGGREGATES
date_trunc usage: https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC

BEGIN;
CREATE temp TABLE trades (
    id bigint GENERATED BY DEFAULT AS IDENTITY,
    closed_a timestamp,
    asset text
) ON COMMIT DROP;
INSERT INTO trades (closed_a)
SELECT
    date '2023-01-01'   interval '10 min' * (random() * i * 10)::int
FROM
    generate_series(1, 10) g (i);
INSERT INTO trades (closed_a)
SELECT
    date '2023-01-02'   interval '10 min' * (random() * i * 10)::int
FROM
    generate_series(1, 10) g (i);
SELECT
    closed_a::date
    ,COUNT(id) FILTER (WHERE date_trunc('hour', closed_a) = closed_a::date) AS "0:00"
    ,COUNT(id) FILTER (WHERE date_trunc('hour', closed_a) = closed_a::date   interval '1 hour') AS "1:00"
    ,COUNT(id) FILTER (WHERE date_trunc('hour', closed_a) = closed_a::date   interval '2 hour') AS "2:00"
    ,COUNT(id) FILTER (WHERE date_trunc('hour', closed_a) = closed_a::date   interval '3 hour') AS "3:00"
    ,COUNT(id) FILTER (WHERE date_trunc('hour', closed_a) = closed_a::date   interval '4 hour') AS "4:00"
    ,COUNT(id) FILTER (WHERE date_trunc('hour', closed_a) = closed_a::date   interval '5 hour') AS "5:00"
FROM
    trades
GROUP BY
    1;
END;
  • Related