将OHLC-Stockmarket数据分组到多个时间范围内 - Mysql

时间:2012-09-20 20:16:48

标签: mysql sql stockquotes group-by

我需要将{Name,DateTime,Open,High,Low,Close,Volume}的股票市场“1min”数据分组到不同的时间范围内,即。 MYSQL上的“5分钟/ 15分钟/ 60分钟”。 Schema建立在sqlfiddle上 - http://sqlfiddle.com/#!2/91433

我找到了一个与MSSQL类似要求的链接 - Group OHLC-Stockmarket Data into multiple timeframes with T-SQL

我尝试按照链接 - http://briansteffens.com/2011/07/19/row_number-partition-and-over-in-mysql/来获取row_number(),在mysql中进行分区以解决问题。

我是sql的新手,有谁能请我指出正确的方向?

4 个答案:

答案 0 :(得分:13)

我知道这是一个老问题,但请看这个“更简单”的解决方案。开盘价和收盘价都有一招。你可能会喜欢它。

SELECT
  FLOOR(MIN(`timestamp`)/"+period+")*"+period+" AS timestamp,
  SUM(amount) AS volume,
  SUM(price*amount)/sum(amount) AS wavg_price,
  SUBSTRING_INDEX(MIN(CONCAT(`timestamp`, '_', price)), '_', -1) AS `open`,
  MAX(price) AS high,
  MIN(price) AS low,
  SUBSTRING_INDEX(MAX(CONCAT(`timestamp`, '_', price)), '_', -1) AS `close`
FROM transactions_history -- this table has 3 columns (timestamp, amount, price)
GROUP BY FLOOR(`timestamp`/"+period+")
ORDER BY timestamp  

时间段以秒为单位

答案 1 :(得分:0)

最后解决了以下mysql查询的问题:

select min(a.mydate),max(a.myhigh) as high,min(a.mylow) as low, 
min(case when rn_asc = 1 then a.myopen end) as open,
min(case when rn_desc = 1 then b.myclose end) as close

from( 

select 
@i := if((@lastdate) != (Floor(unix_timestamp(mydate)/300 )), 1, @i + 1) as rn_asc,
          mydate, myhigh, mylow, myopen, myclose,
          @lastdate := (Floor(unix_timestamp(mydate)/300 ))

from
  onemindata_1,
  (select @i := 0) vt1,
  (select @lastdate := null) vt2 order by mydate

) a

inner join(

select 
@j := if((@lastdate1) != (Floor(unix_timestamp(mydate)/300 )), 1, @j + 1) as rn_desc,
          mydate,myclose,
          @lastdate1 := (Floor(unix_timestamp(mydate)/300 ))

from
  onemindata_1,
  (select @j := 0) vt1,
  (select @lastdate1 := null) vt2 order by mydate desc

)b
on a.mydate=b.mydate
group by (Floor(unix_timestamp(a.mydate)/300 ))

最艰难的部分是获得“特定时间间隔”的打开和关闭。我正在“高,低,开”与'日''关闭'进行内部联接。我可以通过更改(Floor(unix_timestamp(mydate)/ 300))中的分母来切换时间间隔。只要它起作用,目前并不担心性能:)。

答案 2 :(得分:0)

查询有错误,将MIN更改为MAX以获得收盘价:

SELECT
  FLOOR(MIN(`timestamp`)/"+period+")*"+period+" AS timestamp,
  SUM(amount) AS volume,
  SUM(price*amount)/sum(amount) AS wavg_price,
  SUBSTRING_INDEX(MIN(CONCAT(`timestamp`, '_', price)), '_', -1) AS `open`,
  MAX(price) AS high,
  MIN(price) AS low,
  SUBSTRING_INDEX(MAX(CONCAT(`timestamp`, '_', price)), '_', -1) AS `close`
FROM transactions_history -- this table has 3 columns (timestamp, amount, price)
GROUP BY FLOOR(`timestamp`/"+period+")
ORDER BY timestamp  

答案 3 :(得分:0)

我发现@Ruslan的解决方案在MySQL的最新版本中不起作用,因此发布了一个有效的版本:

select 
date_add(str_to_date(date_format(ev.startdatetime, '%Y-%m-%d'),'%Y-%m-%d'), interval 
 hour(ev.startdatetime)*60 + floor(minute(ev.startdatetime)/5)*5 minute) timeframe
 , sum(ev.volume) volume
 , min(ev.startdatetime) mintime
 , substring_index(group_concat(open),',',1) open
 , max(high) as high 
 , min(low) as low
 , substring_index(group_concat(close),',',-1) close
from es1min_v ev
group by 
date_add(str_to_date(date_format(ev.startdatetime, '%Y-%m-%d'),'%Y-%m-%d'), interval 
 hour(ev.startdatetime)*60 + floor(minute(ev.startdatetime)/5)*5 minute)