第一:这个问题不重复。我已经在这里问了这个问题,它已经作为副本关闭了。虽然它与stackoverflow上的其他线程类似,但它实际上要复杂得多。请在假设重复之前阅读帖子:
我正在尝试计算可变日期的变量移动平均线交叉。
即:我想提示用户输入3个值和1个选项。输入是通过Web前端进行的,因此我可以根据输入构建/编辑查询,或者根据需要进行多次查询。
X = 1st moving average term (N day moving average. Any number 1-N)
Y = 2nd moving average term. (N day moving average. Any number 1-N)
Z = Amount of days back from present to search for the occurance of:
option = Over/Under: (> or <. X passing over Y, or X passing Under Y)
X day moving average passing over OR under Y day moving average
within the past Z days.
我的数据库是结构化的:
tbl_daily_data
id
stock_id
date
adj_close
和
tbl_stocks
stock_id
symbol
我有一个btree索引:
daily_data(stock_id, date, adj_close)
stock_id
我坚持这个查询并且在编写它时遇到了很多麻烦。如果变量是固定的,那看起来似乎微不足道,但因为X,Y,Z都是100%相互独立的(例如,可以看看过去100天内的5天移动平均线,或者过去5天内的100天移动平均线)我编码很麻烦。
请帮忙! :(
编辑:我被告知更多上下文可能有帮助吗?我们正在创建一个开放式股票分析系统,用户可以在其中执行趋势分析。我有一个包含3500种股票的数据库,它们的价格历史可以追溯到1970年。
此查询将每天运行,以查找符合特定条件的股票 例如:
10天移动平均线超过20天移动平均线5 天在5天内跨越10天移动平均线20天
55天在100天内超过22天移动平均值
但是每个用户可能对不同的分析感兴趣,因此我不能只存储每行的移动平均线,必须进行计算。
答案 0 :(得分:2)
我不确定我是否完全理解这个问题......但是这样的事情可能会帮助你找到你需要去的地方:sqlfiddle
SET @X:=5;
SET @Y:=3;
set @Z:=25;
set @option:='under';
select * from (
SELECT stock_id,
datediff(current_date(), date) days_ago,
adj_close,
(
SELECT
AVG(adj_close) AS moving_average
FROM
tbl_daily_data T2
WHERE
(
SELECT
COUNT(*)
FROM
tbl_daily_data T3
WHERE
date BETWEEN T2.date AND T1.date
) BETWEEN 1 AND @X
) move_av_1,
(
SELECT
AVG(adj_close) AS moving_average
FROM
tbl_daily_data T2
WHERE
(
SELECT
COUNT(*)
FROM
tbl_daily_data T3
WHERE
date BETWEEN T2.date AND T1.date
) BETWEEN 1 AND @Y
) move_av_2
FROM
tbl_daily_data T1
where
datediff(current_date(), date) <= @z
) x
where
case when @option ='over' and move_av_1 > move_av_2 then 1 else 0 end +
case when @option ='under' and move_av_2 > move_av_1 then 1 else 0 end > 0
order by stock_id, days_ago
基于@Tom H的回答:How do I calculate a moving average using MySQL?