2009-05-18 157 views
5

我需要做的是這樣的:如何使用MySQL計算移動平均數?

SELECT value_column1 
FROM table1 
WHERE datetime_column1 >= '2009-01-01 00:00:00' 
ORDER BY datetime_column1; 

除除value_column1,我還需要檢索的value_column1以前的20個值的moving average

標準SQL是首選,但如果有必要,我會使用MySQL擴展。

回答

18

這只是從我的頭頂,我在路上出了門,所以它是未經考驗的。我也無法想象它在任何大型數據集上表現都會非常好。我確實確認它至少在沒有錯誤的情況下運行。 :)

SELECT 
    value_column1, 
    (
    SELECT 
      AVG(value_column1) AS moving_average 
    FROM 
      Table1 T2 
    WHERE 
      (
       SELECT 
        COUNT(*) 
       FROM 
        Table1 T3 
       WHERE 
        date_column1 BETWEEN T2.date_column1 AND T1.date_column1 
     ) BETWEEN 1 AND 20 
    ) 
FROM 
    Table1 T1 
1

當我遇到類似問題時,由於各種原因,我最終使用臨時表,但它使這更容易!就模式而言,我所做的與您正在做的事情非常相似。

進行模式類似ID身份,日期,結束日期,值。當您選擇時,根據身份標識對前20次進行子選擇。

只有做到這一點,如果你發現自己已經在使用臨時表的其他原因,雖然(我打相同的行遍地針對不同的指標,所以這是有幫助的小數據集)。

+0

我不確定臨時表的位置,我可以在沒有它們的情況下使用您的解決方案。雖然,它有依賴身份欄連續的問題。 – 2009-05-18 20:15:43

+0

身份列連續是臨時表的全部點.....在我的情況下,我有數年和數年的數據,但每個月的數據都是自己處理的。我將數據提取到臨時表並對它們執行許多度量。在我的情況下,使用臨時表(或表值函數)使處理的許多方面更容易。 – overslacked 2009-05-18 21:23:36

2

湯姆H的方法將工作。你可以把它簡化這樣,如果你有一個標識列:

SELECT T1.id, T1.value_column1, avg(T2.value_column1) 
FROM table1 T1 
INNER JOIN table1 T2 ON T2.Id BETWEEN T1.Id-19 AND T1.Id 
+0

我不知道MySQL,但在MS SQL Server中不起作用。 IDENTITY列不保證是順序的或連續的。 – 2009-05-18 18:23:57

0

根據我的經驗,MySQL作爲5.5.X的往往不會對因使用選擇指標,無論是子查詢或加入。這可以對依賴性選擇標準在每行上發生更改的性能產生非常顯着的影響。

移動平均是屬於這一類的查詢的一個例子。執行時間可能會隨着行的平方增加。爲了避免這種情況,選擇了一個數據庫引擎,可以對依賴選擇執行索引查找。我發現postgres可以有效解決這個問題。

1

我的解決方案在表中添加了一個行號。以下示例代碼可能會有所幫助:

set @MA_period=5; 
select id1,tmp1.date_time,tmp1.c,avg(tmp2.c) from 
(select @b:[email protected]+1 as id1,date_time,c from websource.EURUSD,(select @b:=0) bb order by date_time asc) tmp1, 
(select @a:[email protected]+1 as id2,date_time,c from websource.EURUSD,(select @a:=0) aa order by date_time asc) tmp2 
where id1>@MA_period and id1>=id2 and id2>([email protected]_period) 
group by id1 
order by id1 asc,id2 asc 
1

我意識到這個答案大約7年太晚了。我有類似的要求,並認爲我會分享我的解決方案,以防其他人有用。

有一些MySQL的擴展技術分析,包括一個簡單的移動平均線。他們真的很容易安裝和使用:https://github.com/mysqludf/lib_mysqludf_ta#readme

一旦你安裝了UDF(每指令自述),您可以在select語句這樣一個簡單的移動平均線:

SELECT TA_SMA(value_column1, 20) AS sma_20 FROM table1 ORDER BY datetime_column1