2015年6月6日 星期六

關於 MySQL 中使用 AVG 聚合函數與 LIMIT 的問題

昨晚檢查一周來的財工程式執行數據, 發現計算出來的平均值不正確, 在 Google 搜尋過後才搞清楚, 原來 MySQL 的 LIMIT 功能不是我想的那樣, 它是在最後才 apply 的, 例如下面的 SQL :

"SELECT AVG(close) FROM ".$table." ORDER BY trade_date DESC LIMIT 5";

MySQL 會先對 close 欄位的所有數據取平均值後, 再取前面五筆, 由於平均值結果只有一筆, 所以也就得到一筆資料, 但卻是全部 close 的平均, 而非最近五筆 close 的平均, 參考下列文章 :

# Select average from MySQL table with LIMIT
# Subquery with limit clause : Sub query « Select Clause « SQL / MySQL
# Limit not working for avg query
# avg() and limit

"you have to consider how LIMIT works. It's the last thing that happens as the query is executed."

所以, 上面所有計算平均值的 SQL 指令都必須修改, 例如 MA5 要改成 :

      $SQL="SELECT AVG(items.close) FROM (SELECT close FROM ".$table.
           " ORDER BY trade_date DESC LIMIT 5) AS items";

亦即要採取 sub-query 的兩層查詢方法, 先用一個 SELECT ... LIMIT  5 指令找出最近的五筆紀錄, 並命名為 items, 再用 AVG 去計算 close 欄位的平均值.

以上資料亦同步修改之前的文章, 參見 :

# 用 PHP 計算移動平均線 MA 與指數移動平均線 EMA 的方法



沒有留言 :