按 5、10、15 分钟块对带时间戳的记录进行分组
Group timestamped record by 5, 10, 15 minutes block
我的 table,
中有以类似格式存储的每分钟财务记录
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。
您可以使用generate_series()
创建您想要的任何范围
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
;
然后检查您的记录是否在该范围内。
您应该使用 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 epoch重新转换为timestamp 使用
to_timestamp(floor((extract('epoch' from dt) / 300)) * 300) as ts
不清楚您是否希望在同一个查询中获得所有 "block" 结果,如果您想要烛台图,我假设是的。我还从逻辑上推断出每列的正确聚合函数(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
上测试
我的 table,
中有以类似格式存储的每分钟财务记录 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。
您可以使用generate_series()
创建您想要的任何范围
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
;
然后检查您的记录是否在该范围内。
您应该使用 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 epoch重新转换为timestamp 使用
to_timestamp(floor((extract('epoch' from dt) / 300)) * 300) as ts
不清楚您是否希望在同一个查询中获得所有 "block" 结果,如果您想要烛台图,我假设是的。我还从逻辑上推断出每列的正确聚合函数(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
上测试