计算移动平均线MySQL?

sur*_*190 9 mysql sql database

美好的一天,

我使用以下代码计算9天移动平均值.

SELECT SUM(close)
FROM tbl
WHERE date <= '2002-07-05'
AND name_id = 2
ORDER BY date DESC
LIMIT 9
Run Code Online (Sandbox Code Playgroud)

但它不起作用,因为它在调用限制之前首先计算所有返回的字段.换句话说,它将计算在该日期之前或之前的所有关闭,而不仅仅是最后的9.

所以我需要从返回的select中计算SUM,而不是直接计算它.

IE浏览器.从SELECT中选择SUM ...

现在我将如何做到这一点,它是否非常昂贵,还是有更好的方法?

Gor*_*off 12

如果你想要每个日期的移动平均线,那么试试这个:

SELECT date, SUM(close),
       (select avg(close) from tbl t2 where t2.name_id = t.name_id and datediff(t2.date, t.date) <= 9
       ) as mvgAvg
FROM tbl t
WHERE date <= '2002-07-05' and
      name_id = 2
GROUP BY date
ORDER BY date DESC
Run Code Online (Sandbox Code Playgroud)

它使用相关子查询来计算9个值的平均值.

  • @ surfer100奇怪然后这不是公认的答案 (4认同)

Luk*_*der 7

从 MySQL 8 开始,您应该为此使用窗口函数。使用windowRANGE子句,你可以在一个区间上创建一个逻辑窗口,这个功能非常强大。像这样的东西:

SELECT
  date,
  close,
  AVG (close) OVER (ORDER BY date DESC RANGE INTERVAL 9 DAY PRECEDING)
FROM tbl
WHERE date <= DATE '2002-07-05'
AND name_id = 2
ORDER BY date DESC
Run Code Online (Sandbox Code Playgroud)

例如:

WITH t (date, `close`) AS (
  SELECT DATE '2020-01-01', 50 UNION ALL
  SELECT DATE '2020-01-03', 54 UNION ALL
  SELECT DATE '2020-01-05', 51 UNION ALL
  SELECT DATE '2020-01-12', 49 UNION ALL
  SELECT DATE '2020-01-13', 59 UNION ALL
  SELECT DATE '2020-01-15', 30 UNION ALL
  SELECT DATE '2020-01-17', 35 UNION ALL
  SELECT DATE '2020-01-18', 39 UNION ALL
  SELECT DATE '2020-01-19', 47 UNION ALL
  SELECT DATE '2020-01-26', 50
)
SELECT
  date,
  `close`,
  COUNT(*) OVER w AS c,
  SUM(`close`) OVER w AS s,
  AVG(`close`) OVER w AS a
FROM t
WINDOW w AS (ORDER BY date DESC RANGE INTERVAL 9 DAY PRECEDING)
ORDER BY date DESC
Run Code Online (Sandbox Code Playgroud)

导致:

date      |close|c|s  |a      |
----------|-----|-|---|-------|
2020-01-26|   50|1| 50|50.0000|
2020-01-19|   47|2| 97|48.5000|
2020-01-18|   39|3|136|45.3333|
2020-01-17|   35|4|171|42.7500|
2020-01-15|   30|4|151|37.7500|
2020-01-13|   59|5|210|42.0000|
2020-01-12|   49|6|259|43.1667|
2020-01-05|   51|3|159|53.0000|
2020-01-03|   54|3|154|51.3333|
2020-01-01|   50|3|155|51.6667|
Run Code Online (Sandbox Code Playgroud)


Aka*_*ash 5

使用类似的东西

SELECT 
  sum(close) as sum,
  avg(close) as average
FROM (
    SELECT 
      (close)
    FROM 
      tbl
    WHERE 
      date <= '2002-07-05'
      AND name_id = 2
    ORDER BY 
      date DESC
    LIMIT 9 ) temp
Run Code Online (Sandbox Code Playgroud)

内查询返回所有在过滤的行desc顺序,然后avg,sum向上的行返回.

query您给出的不起作用的原因是由于sum首先计算并且在已经计算LIMIT之后应用该子句sum,因此给出了sum所有存在的行

  • ..这将返回一个值.移动平均线是指"n"个记录的每个日期的单独值. (7认同)