Групповая отметка времени с интервалом 5, 10, 15 минут - PullRequest
0 голосов
/ 06 мая 2018

У меня есть минутные финансовые записи, хранящиеся в похожем формате в моей таблице,

         dt          |   open   |   high   |   low    |  close   |  vol  
---------------------+----------+----------+----------+----------+-------
 2018-05-04 15:30:00 | 171.0000 | 171.3000 | 170.9000 | 171.0000 | 42817
 2018-05-04 15:29:00 | 170.8000 | 171.0000 | 170.8000 | 170.9500 | 32801
 2018-05-04 15:28:00 | 170.8500 | 171.0000 | 170.8000 | 170.8000 | 22991
 2018-05-04 15:27:00 | 170.8500 | 170.8500 | 170.7500 | 170.8000 | 40283
 2018-05-04 15:26:00 | 170.9500 | 171.0000 | 170.8000 | 170.8500 | 46636

и т. Д.

Я хочу сгруппировать их в блоки по 5, 10, 60 минут, как подсвечники. Использование date_trunc('hour', dt) невозможно, так как я хочу сгруппировать их как блоки последних 60 минут, последних 15 минут и т. Д.

Я использую PostgreSQL.

Ответы [ 2 ]

0 голосов
/ 06 мая 2018

Вы должны использовать GROUP BY с:

floor(extract('epoch' from dt) / 300)

чтобы ваши данные группировались с интервалом в 5 минут. 300 - количество секунд в 5 минутах. Таким образом, если вы хотите 10 минут, вы делите на 600. Если вы хотите 1 час, на 3600.

Если вы хотите, чтобы ваш интервал начинался с 00 05 10, используйте floor(). Если вы хотите, чтобы они закончили в 00, 05, 10, используйте ceil()

В предложении SELECT необходимо преобразовать эпоху Unix , использованную в GROUP BY, в отметку времени , используя

to_timestamp(floor((extract('epoch' from dt) / 300)) * 300)  as ts

Непонятно, хотите ли вы, чтобы все результаты «блока» были в одном и том же запросе, я предположил, что да, если вы хотите график свечей. Я также логически вывел правильную статистическую функцию (MIN, MAX, AVG, SUM) для каждого столбца, следуя их именам. Возможно, вам придется адаптировать это.

Вот и мы:

 SELECT '5 minutes' as block,
        to_timestamp(floor((extract('epoch' from dt) / 300)) * 300)  as ts, 
        round(AVG(open),4) as avg_open,  
        round(MAX(high),4) as max_high, 
        round(MIN(low),4) as min_low, 
        round(AVG(close),4) as avg_close,  
        SUM(vol) as sum_vol  
 FROM mytable
 GROUP BY floor(extract('epoch' from dt) / 300)

 UNION ALL

  SELECT '10 minutes' as block,
        to_timestamp(floor((extract('epoch' from dt) / 600)) * 600)  as ts, 
        round(AVG(open),4) as avg_open,  
        round(MAX(high),4) as max_high, 
        round(MIN(low),4) as min_low, 
        round(AVG(close),4) as avg_close,  
        SUM(vol) as sum_vol  
 FROM mytable
 GROUP BY floor(extract('epoch' from dt) / 600)

  UNION ALL

  SELECT '1 hour' as block,
        to_timestamp(floor((extract('epoch' from dt) / 3600)) * 3600)  as ts, 
        round(AVG(open),4) as avg_open,  
        round(MAX(high),4) as max_high, 
        round(MIN(low),4) as min_low, 
        round(AVG(close),4) as avg_close,  
        SUM(vol) as sum_vol  
 FROM mytable
 GROUP BY floor(extract('epoch' from dt) / 3600)

Результаты:

    block       ts                  avg_open    max_high    min_low     avg_close   sum_vol
    5 minutes   04.05.2018 17:30:00 171         171,3       170,9       171         42817
    5 minutes   04.05.2018 17:25:00 170,8625    171         170,75      170,85      142711
    10 minutes  04.05.2018 17:20:00 170,8625    171         170,75      170,85      142711
    10 minutes  04.05.2018 17:30:00 171         171,3       170,9       171         42817
    1 hour      04.05.2018 17:00:00 170,89      171,3       170,75      170,88      185528

Проверьте это на REXTESTER

0 голосов
/ 06 мая 2018

Вы можете использовать generate_series() для создания любого диапазона, который вы хотите

SQL DEMO:

SELECT dd as start_range, dd + '30 min'::interval as end_range
FROM generate_series
        ( '2018-05-05'::timestamp 
        , '2018-05-06'::timestamp
        , '30 min'::interval) dd
        ;

Затем проверьте, попадает ли ваша запись в этот диапазон.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...