组时间戳记录5,10,15分钟

时间:2018-05-06 06:41:10

标签: sql postgresql psql

我在表格中以类似的格式存储了一分钟到一分钟的财务记录,

         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 :(得分:3)

您应该使用GROUP BY

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

让您的数据以5分钟为间隔进行分组。 300是5分钟内的秒数。因此,如果您想要10分钟,则除以600.如果您想要1小时,则需要3600分钟。

如果您希望时间间隔从00 05 10开始,请使用floor()。如果您希望它们在00,05,10完成,请使用ceil()

SELECT子句中,您应该使用

GROUP BY中使用的 Unix纪元重新转换为时间戳
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

上测试

答案 1 :(得分:0)

您可以使用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
        ;

然后检查您的记录是否属于该范围。