我有一个查询来按时间执行聚合记录,但我有一些错误。
我的情况:我将MySQL db 5.6中的股票市场数据存储在从0900到1730的每分钟一条记录中,即每天511条记录
我需要在不同的时间范围内汇总这些数据,假设为5分钟,那么
volume5min - >总量0900:0904
open5min - > 0900记录的开放值(范围内的第一个开放值)
close5min - > 0904记录的近似值(范围内的最后一个接近值)
high5min - > 0900至0904范围内的最高值
low5min - > 0900至0904范围内的最低值
等等。
我有一个查询来完成此操作,但是我在打开和关闭聚合值时出现错误
SELECT
floor(cast(time as SIGNED) / 5) as timeInterval,
date,
time,
MAX(high) AS high,
MIN(low) as low,
SUM(volume) as volume,
(select
open
from
atlantia a2
where
a1.time = a2.time
order by time
limit 1) as open,
(select
close
from
atlantia a2
where
a1.time = a2.time
order by time desc
limit 1) as close
FROM
atlantia a1
GROUP BY date , timeInterval
这是我执行查询的原因
打开和关闭没有正确聚合,而其他列似乎很好。
更重要的是,更改总时间范围我得到的时间不正确,例如下面的60分钟示例
从0900开始我应该有1000,1100等等,而现在我也有1020,1140等。
列类型为:
日期:CHAR 时间:CHAR 所有其余的都是DOUBLE但是Volume是INTEGER。
如何修改此查询以正确汇总值?
编辑:为了验证您的上一次查询,我手动检查了任何一个小时,这些是我应该得到的正确值
您的查询会返回关闭值的差异,其余的都没关系
关闭值应该是时间范围的最后一条记录,即0900和0959之间的时间关闭是关闭列中的0959值。
编辑2:看来我已经找到了诀窍的所在,现在有了这个查询,一切正常
SELECT
Sub1.timeInterval,
a1.date,
MIN(a1.time),
MAX(a1.high) AS high,
MIN(a1.low) as low,
SUM(a1.volume) as volume,
a2.open as open,
a3.close as close
FROM atlantia a1
INNER JOIN
(
SELECT floor( (cast( SUBSTRING(time,1,2) AS SIGNED ) * 60 + cast( SUBSTRING(time,3,2) AS SIGNED )) /60 ) AS timeInterval, MIN(time) AS minTime, MAX(time) AS maxtime
FROM atlantia
GROUP BY timeInterval
) Sub1
ON floor( (cast( SUBSTRING(a1.time,1,2) AS SIGNED ) * 60 + cast( SUBSTRING(a1.time,3,2) AS SIGNED )) /60 ) = Sub1.timeInterval
INNER JOIN atlantia a2 ON a2.time = Sub1.minTime AND a1.date = a2.date
INNER JOIN atlantia a3 ON a3.time = Sub1.maxtime AND a1.date = a3.date
GROUP BY a1.date , timeInterval
如果我想在不同的时间范围内聚合,即5分钟怎么办?我只用/ 5改变/ 60?
由于
答案 0 :(得分:1)
我可以发现一些问题。
您正在将时间存储在角色字段中,当投射时,签名时间为10点20分被视为1020而不是10 * 60分钟+20分钟。因此当除以60时10:00是16而10:20是17时,因此在你的代码中它们是2个不同的时间间隔。
另一个问题是您已将时间作为字段返回,而不在GROUP BY子句中指定。它将返回的时间值来自未确定的行(通常是第一行但不总是)。可能最容易指定MIN(时间)。
SELECT
floor( (cast( SUBSTRING(time,1,2) AS SIGNED ) * 60 + cast( SUBSTRING(time,3,2) AS SIGNED )) /60 ) AS timeInterval,
date,
MIN(time),
MAX(high) AS high,
MIN(low) as low,
SUM(volume) as volume,
(select
open
from
atlantia a2
where
a1.time = a2.time
order by time
limit 1) as open,
(select
close
from
atlantia a2
where
a1.time = a2.time
order by time desc
limit 1) as close
FROM
atlantia a1
GROUP BY date , timeInterval
可以清理sql以删除子查询。
修改
有一个游戏,这可能会这样做,但不确定效率,没有表我无法测试: -
SELECT
Sub1.timeInterval,
a1.date,
MIN(a1.time),
MAX(a1.high) AS high,
MIN(a1.low) as low,
SUM(a1.volume) as volume,
MIN(a2.open) as open,
MIN(a3.close) as close
FROM atlantia a1
INNER JOIN
(
SELECT floor( (cast( SUBSTRING(time,1,2) AS SIGNED ) * 60 + cast( SUBSTRING(time,3,2) AS SIGNED )) /60 ) AS timeInterval, MIN(time) AS minTime, MAX(time) AS maxtime
FROM atlantia
GROUP BY timeInterval
) Sub1
ON floor( (cast( SUBSTRING(a1.time,1,2) AS SIGNED ) * 60 + cast( SUBSTRING(a1.time,3,2) AS SIGNED )) /60 ) = Sub1.timeInterval
INNER JOIN atlantia a2 ON a2.time = Sub1.minTime AND a1.date = a2.date
INNER JOIN atlantia a3 ON a3.time = Sub1.minTime AND a1.date = a3.date
GROUP BY a1.date , timeInterval