我正在尝试使用MySQL的SQL查询来计算200行指数移动平均值(EMA)。每行取决于前一行的值。公式是:
EMA = ((price - EMA(previous_average)) * (2 / (200 + 1))) + EMA(previous_average)
我的表最初看起来像
id price average
---------------------------
1 29.05 29.05000000
2 29.04 0.00000000
3 29.06 0.00000000
4 29.05 0.00000000
(我手动将第一行的“平均值”设置为“价格”,以便下面的查询具有初始值)
运行此查询
UPDATE
quotes
INNER JOIN
quotes AS quotes_previous ON quotes_previous.id = table.id - 1
SET
table.average = ((quotes.price - quotes_previous.average) * (2 / (200 + 1)) + quotes_previous.average)
where
quotes.id > 1
我的表格看起来像
id price average
---------------------------
1 29.05 29.05000000
2 29.04 29.04990050
3 29.06 1.13937059
3 29.05 1.13927205
正如您所看到的,除前两行外,其他所有人的平均值显然都不正确。
我认为问题是查询需要按id顺序更新行。但是当我向查询添加“ORDER BY id”时,我得到“错误1221(HY000):UPDATE和ORDER BY的使用不正确。”我相信我不能在UPDATE查询中使用ORDER BY和JOIN。
那么,如何运行依赖于前一行值的UPDATE查询?
答案 0 :(得分:1)
试试这个
UPDATE quotes q INNER JOIN
(SELECT id,
price,
((price - @prev) * (2 / (200 + 1))) + @prev average,
@prev = ((price - @prev) * (2 / (200 + 1))) + @prev
FROM quotes, (SELECT @prev := (SELECT price FROM quotes ORDER BY id LIMIT 1) i) n
ORDER BY id) t ON q.id=t.id
SET q.average = t.average
输出
+------+-------+-------------+
| id | price | average |
+------+-------+-------------+
| 1 | 29.05 | 29.05000000 |
| 2 | 29.04 | 29.04990050 |
| 3 | 29.06 | 29.05009950 |
| 4 | 29.05 | 29.05000000 |
+------+-------+-------------+
重新运行是安全的,因为它从id值最低的行的价格列中获取第一个平均值。