CREATE MATERIALIZED VIEW weather_1h AS
DECLARE
@sample_interval := 1h,
@sample_interval_str := '1h'
with w_max_min as (
select *,
FIRST_VALUE(ts::long) over(partition by timestamp_floor(@sample_interval_str, ts) order by temperature ASC) as ranking_min,
FIRST_VALUE(ts::long) over(partition by timestamp_floor(@sample_interval_str, ts) order by temperature DESC) as ranking_max
FROM weather_behavior
)
SELECT
ts,
max(temperature) AS max_value,
ranking_max::TIMESTAMP,
min(temperature) AS min_value,
ranking_min::TIMESTAMP
FROM w_max_min
SAMPLE BY @sample_interval
Actually maybe not asof join, as it would join only on same or previous timestamp. You might try asof join but reversing the order, or go with inner joins, but then you need to limit to 1 the result of each join
I think when obtaining the maximum/minimum values, we often also obtain the moments when they occur. Is there a built-in function method available to simplify this operation?
It should be possible to achieve this without window functions, by joining back to the table. This is an example using demo.questdb.io
WITH btcusd AS (
trades WHERE timestamp IN today() AND symbol = 'BTC-USD'
), minmax AS (
SELECT
timestamp,
max(price) maxPrice,
min(price) minPrice,
FROM btcusd
SAMPLE BY 1h
), min_joined AS (
SELECT minmax.timestamp as hour,
minPrice,
btcusd.timestamp as minTime
FROM minmax
JOIN btcusd
ON price = minPrice
LIMIT 1
), max_joined AS (
SELECT minmax.timestamp as hour,
maxPrice,
btcusd.timestamp as maxTime
FROM minmax
JOIN btcusd
ON price = maxPrice
LIMIT 1
)
SELECT minPrice, minTime, maxPrice, maxTime
FROM min_joined
JOIN max_joined ON hour;
minPrice
minTime
maxPrice
maxTime
117019.1
2025-07-22T04:42:43.249000Z
117525.3
2025-07-22T08:26:07.048000Z
It will need a closer look, but in principle, you get your min/max result set and self-join it. Maybe this puts you on a closer path?
Okay, for now, the simplest will either be a join, or just doing it in two queries (get the max values first, then find the timestamps second).
We’re discussing this internally and will see what would be the best way to make this easy i.e. returning other parts of the row that match the aggregate.
Thank you very much for your reply.This is exactly the result I expected: “returning other parts of the row that match the aggregate”,hope for further progress