1

我正在尝试使用带有 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 查询?

4

1 回答 1

2

尝试这个

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 的行的价格列中获取第一个平均值。

于 2013-03-02T09:55:26.753 回答