2013-03-01 63 views
1

我試圖計算出200列指數使用與MySQL的SQL查詢移動平均線(EMA)。每行都取決於前一行的值。其計算公式爲:UPDATE查詢依賴於以前的記錄值

EMA = ((price - EMA(previous_average)) * (2/(200 + 1))) + EMA(previous_average) 

我的表initallly看起來像

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。

所以,我怎樣才能運行更新查詢依賴於上一行的價值?

+0

你的意思是前面的行*更新*值或更新前的值? – 2013-03-01 19:11:48

+0

如果你想使用前一行的更新值,答案是「不,你不能這樣做。」更新作爲單個事務執行。除非所有值已經進入表格,否則任何給定值都不會進入表格。您需要使用遊標執行此操作 - 或者查找另一種表達算術的方法。 – 2013-03-01 19:13:30

+0

@戈登這就是我所害怕的。好的,有時間寫一個存儲過程......除非有人有一個更簡單的解決方案? – 2013-03-01 19:27:41

回答

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最低。

+0

@ChadJohnson有幫助嗎? – peterm 2013-03-04 14:10:00

+0

該死的。我看到這太遲了。我結束了使用存儲過程。不過謝謝你。 – 2013-03-04 17:14:53

+0

不客氣。祝你好運。 – peterm 2013-03-04 18:45:00