如何编写汇总外汇蜡烛数据的查询?

Bry*_*yan 5 sql postgresql

我有一个包含以下架构的财务数据表:

         Table "public.candles"
   Column   |      Type      | Modifiers 
------------+----------------+-----------
 posix_time | bigint         | not null
 low        | numeric(8,2)   | not null
 high       | numeric(8,2)   | not null
 open       | numeric(8,2)   | not null
 close      | numeric(8,2)   | not null
 volume     | numeric(23,16) | not null
Indexes:
    "candles_pkey" PRIMARY KEY, btree (posix_time)
Run Code Online (Sandbox Code Playgroud)

每支蜡烛间隔一分钟.我想将数据汇总成蜡烛,间隔时间为5分钟,1小时,1天等.

我可以聚合posix_time,high,low,并volume与超过五分钟的时间间隔

SELECT posix_time/(60*5)*(60*5) AS new_posix_time,
       max(high)                AS new_high,
       min(low)                 AS new_low,
       sum(volume)              AS new_volume
FROM candles
GROUP BY new_posix_time
Run Code Online (Sandbox Code Playgroud)

并用适当的变量计算新的openclose

SELECT posix_time/(60*5)*(60*5) AS new_posix_time,
       open                     AS new_open
FROM (SELECT open,
             posix_time,
             ROW_NUMBER() OVER (PARTITION BY posix_time/(60*5)*(60*5)
                                    ORDER BY posix_time ASC) AS r
      FROM candles
     ) AS o
WHERE o.r = 1
Run Code Online (Sandbox Code Playgroud)

正如这个问题所建议的,但我无法弄清楚如何将它们组合成一个查询.

我需要使用连接吗?子查询?完全重组查询?

Gor*_*off 1

您可以用来generate_series()获取您正在寻找的时间范围。然后就可以使用left join和聚合了。像这样的东西:

select t.ts,
       min(low) as low, max(high) as high, sum(volume) as volume
from generate_series('2016-01-01'::timestamp, '2016-01-02'::timestamp, interval '5 minute'
                    ) t(ts) left join
     candles c
     on '1970-01-01' + c.posix_time * interval '1 second' between t.ts and t.ts + interval '5 minute'
group by t.ts;
Run Code Online (Sandbox Code Playgroud)

编辑:

获取打开和关闭时间需要多一级处理:

select ts, min(low) as low, max(high) as high, sum(volume) as volume,
       min(open) as open, min(close) as close
from (select t.*, c.*,
             first_value(open) over (partition by t.ts order by c.posix_time asc) as open,
             first_value(open) over (partition by t.ts order by c.posix_time desc) as close
      from generate_series('2016-01-01'::timestamp, '2016-01-02'::timestamp, interval '5 minute'
                          ) t(ts) left join
           candles c
           on '1970-01-01' + c.posix_time * interval '1 second' between t.ts and t.ts + interval '5 minute'
     ) t
group by ts;
Run Code Online (Sandbox Code Playgroud)