编辑
这个版本应该是灵活的,我希望不要太慢。由于不知道表中的内容以及表的名称是什么意思,我假设一个表价格表,代码='AAA','BBB' 等等,close 表示价格。您给定的日期应该是“2015-09-12”。用你喜欢的任何东西替换“2015-09-12”。
30 应该是交易天数。用'limit 30'中的任何你想要的替换。
股票代码 |代码 |日期 |开放|高 |低 |关闭 |音量
试试这个版本
select pt.code, sum(pt.close) / count(*) as average
from pricetable pt
inner join
( select distinct `date`
from pricetable
where `date` <= '2015-09-12' # your given date
order by `date` desc
limit 30 # the number of trading days
) as d on d.`date` = pt.`date`
where code in ("AAA","BBB","CCC")
group by code
order by average desc;
如果子选择太慢,请使用后面的一些版本。
您绝对应该制作一个包含日历日的表格,并且他们会得到一个列来标记交易日。如果它们还包含对 30 天前和 90 天前的引用会容易得多。
create table calendar_days
(
id int(11) not null auto_increment primary key,
calday date not null,
is_trading tinyint,
trading_before_30 date,
trading_before_90 date
);
然后就简单了:
select pt.stockname, sum(pt.closing_price) / count(*) as avg_close
from calendar_days d
inner join pricetable pt on pt.day between d.calday and d.trading_before_30
where d.calday = '2015-08-15'
group by pt.stockname;
您可以从股票表中轻松填写日历日表。
编辑:这样您可以在当天的第一次请求时填写它,假设只有个交易日在此表中。
insert into calendar_days (calday, is_trading)
select distinct day, 1
from pricetable pt
where pt.day > (select max(calday from calendar_days);
update calendar_days d1
inner join calendar_days d2 on d2.nr = d1.nr - 29
set d1.trading_before_30 = d2.calday
where d1.trading_before_30 is null;
您当然可以尝试从您的股票价格表中动态构建最近 30 个交易日的列表,但是该表每天有很多条目,因此这会不必要地减慢您的查询速度 - 日期会发生变化很少,每天只有一次。
您甚至可以在结束日表中添加一个触发器,以便在每次插入时检查是否要重新填写日历日。
没有该表的版本如下所示:
drop temporary table if exists tmp_days;
create temporary table tmp_days (tradingday date not null primary key);
insert into tmp_days
select distinct `day`
from pricetable
where day <= '2015-08-15'
order by day desc limit 30;
然后
select pt.stockname, sum(pt.price) / count(*) as average
from pricetable pt
inner join tmp_days d on d.tradingday = pt.day;
临时表仅在一个连接中可见。