Заданное время / интервал для расчета значения открытия / максимума / минимума / закрытия в каждой сгруппированной информации
Предположим, что необработанные данные:
Timestamp High Low Volume
10:24.22345 100 99 10
10:24.23345 110 97 20
10:24.33455 97 89 40
10:25.33455 60 40 50
10:25.93455 40 20 60
При времени выборки 1 секунда выходные данные должны быть следующими (они сгруппированы по секундам):
Timestamp Open Close High Low Volume
10:24 82 83 110 89 70
10:25 50 40 60 20 110
Open
означает цену самых ранних данных в группеClose
означает цену последних данных в группеVolume
означает сумму (объем) в группе
Единица выборки варьируется от 1 second, 5 sec, 1 minute, 1 hour, 1 day, ...
Теперь я могу получить High, Low, Volume с помощью следующего SQL:
SELECT date_trunc(\'#{interval}\', ticktime) AS ticktime_stamp,
max(bid_price) as high,
min(bid_price) as low,
sum(bid_volume) as volume,
max(product_type) as product_type
FROM czces
WHERE ticktime >= \'#{begin_time}\'::timestamp
AND ticktime < \'#{end_time}\'::timestamp
AND product_type =\'#{product_type}\'
GROUP BY 1
ORDER BY ticktime_stamp ASC
Но как получить open
, close
значение в каждой группе на основе вышеуказанного запроса?
2 ответа
Решение
Вы можете использовать оконные функции в сочетании с DISTINCT ON
для этого:
SELECT DISTINCT ON (1)
date_trunc('#{interval}', ticktime) AS ticktime_stamp
, max(bid_price) OVER w AS high
, min(bid_price) OVER w AS low
, sum(bid_volume) OVER w AS volume
, max(product_type) OVER w AS product_type
, min(product_type) OVER w AS product_type
, first_value(bid_price) OVER w AS open
, last_value(bid_price) OVER w AS close
FROM czces
WHERE ticktime >= '#{begin_time}'::timestamp
AND ticktime < '#{end_time}'::timestamp
AND product_type ='#{product_type}'
WINDOW w AS (PARTITION BY date_trunc('#{interval}', ticktime) ORDER BY ticktime
ROWS BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING)
ORDER BY 1;
Объяснение для пользовательской оконной рамы:
- Как использовать кольцевую структуру данных в оконных функциях
- Оконная функция PostgreSQL: разделение по сравнению
Объяснение для DISTINCT ON
:
Скорее всего, это искомый запрос, но без реальных данных тестирования трудно быть уверенным.
SELECT
min(date_trunc('second', "Timestamp")) OVER minutes "Timestamp",
first_value("Price") OVER minutes "Open",
last_value("Price") OVER minutes "Close",
max("High") OVER minutes "High",
min("Low") OVER minutes "Low",
sum("Volume") OVER minutes "Volume"
FROM czces
WINDOW minutes AS (
PARTITION BY date_trunc('second', "Timestamp")
ORDER BY "Timestamp"
);