2014-01-30 117 views
0

我有一个查询按时间执行聚合记录,但我有一些错误。按时间汇总记录

我的情况:我的股票行情数据每分钟5.6一个创纪录的0900存储在MySQL数据库VERS高达1730,这是511点的记录每天

enter image description here

我需要汇总这些数据进行不同的时间帧,让我们假设5分钟,使得

volume5min - >总和体积0900:0904

open5min - 为0900记录(在范围内首开值)

close5min>开值 - >最高每日0900时至价值 - 0904记录(在范围内最后收盘值)

high5min>收盘值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 

这是我得到执行查询

enter image description here

打开和关闭是没有正确汇总,而其他列看起来不错。

更重要的是,改变总的时间框架,我得到不正确的时间,如下面

enter image description here

从9时开始的60分钟的例子,我应该有1000,1100等,而现在我也有1020,1140等

列类型有:

日期:CHAR 时间:CHAR 其余全部为双卷却是INTEGER。

如何修改此查询以正确汇总值?

编辑:,以验证您的最后一个查询,我已经手动检查任何一个小时,这些都是正确的价值观,我应该得到

enter image description here

查询返回的密切价值观的差异,所有其余它的确定

enter image description here

关闭值应为时限的最后一个记录,即时间betwee n 0900和0959 close是紧密列中的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

我最后的查询工作正常60分钟,也是5分钟,10分钟等等。对于奇数时间帧划分有聚集问题,例如7或11分钟。任何有关如何解决真正赞赏的建议。感谢 –

回答

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 
+0

@Kickstart ...感谢您的代码修复了时间间隔问题,但仍然存在打开和关闭的错误值。 –

+0

认为存在的问题是,您获得的是与任何时间段开始时的时间匹配的任何行的打开和关闭值,但您并未检查日期。我会玩一个更好的解决方案。 – Kickstart

+0

@Albertoacepsut - 快速玩 – Kickstart