计算移动平均MySQL?
美好的一天,计算移动平均MySQL?
我正在使用以下代码来计算9天移动平均线。
SELECT SUM(close)
FROM tbl
WHERE date <= '2002-07-05'
AND name_id = 2
ORDER BY date DESC
LIMIT 9
但它不起作用,因为它在限制被调用之前首先计算所有返回的字段。换句话说,它会计算所有关闭之前或等于该日期,而不仅仅是最后9.所以我需要从返回的选择计算SUM,而不是直接计算它。
IE。从SELECT中选择SUM ...
现在我该如何去做这件事,它是非常昂贵的还是有更好的方法?
使用类似
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
内查询在desc
为了返回所有过滤行,然后你avg
,sum
了这些行返回。
之所以被你给不工作的query
是由于事实sum
计算第一和LIMIT
子句已经计算出sum
后应用,给你所有存在的行的sum
如果你想为每个日期的均线,那就试试这个:
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
它使用相关子查询来计算9个值的平均值。
更好。我在日常触发器上使用这个功能,所以我只需要一个特定日期的MA,因为我只是为了速度而将数据库中的9日均线保存起来。但有了这个,我可以让用户为移动平均线设定他们自己的时间段,下行速度就是速度。谢谢。 – surfer190 2014-08-23 07:40:25
@ surfer100奇怪的是,这不是被接受的答案 – Strawberry 2016-03-24 07:47:05
颠覆这个古老的线程,因为我正在寻找使用纪元时间戳相同的答案。这里的问题是这不包括周末。 – fractal5 2017-12-13 17:49:39
这个查询速度快:
select date, name_id,
case @i when name_id then @i:=name_id else (@i:=name_id)
and (@n:=0)
and (@a0:=0) and (@a1:=0) and (@a2:=0) and (@a3:=0) and (@a4:=0) and (@a5:=0) and (@a6:=0) and (@a7:=0) and (@a8:=0)
end as a,
case @n when 9 then @n:=9 else @n:[email protected]+1 end as n,
@a0:[email protected],@a1:[email protected],@a2:[email protected],@a3:[email protected],@a4:[email protected],@a5:[email protected],@a6:[email protected],@a7:[email protected],@a8:=close,
(@[email protected][email protected][email protected][email protected][email protected][email protected][email protected][email protected])/@n as av
from tbl,
(select @i:=0, @n:=0,
@a0:=0, @a1:=0, @a2:=0, @a3:=0, @a4:=0, @a5:=0, @a6:=0, @a7:=0, @a8:=0) a
where name_id=2
order by name_id, date
如果您需要超过50个或100个值的平均值,这是繁琐写,但是 值得努力。速度接近有序选择。
的另一种技术是做一个表:
CREATE TABLE `tinyint_asc` (
`value` tinyint(3) unsigned NOT NULL default '0',
PRIMARY KEY (value)
) ;
INSERT INTO `tinyint_asc` VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23),(24),(25),(26),(27),(28),(29),(30),(31),(32),(33),(34),(35),(36),(37),(38),(39),(40),(41),(42),(43),(44),(45),(46),(47),(48),(49),(50),(51),(52),(53),(54),(55),(56),(57),(58),(59),(60),(61),(62),(63),(64),(65),(66),(67),(68),(69),(70),(71),(72),(73),(74),(75),(76),(77),(78),(79),(80),(81),(82),(83),(84),(85),(86),(87),(88),(89),(90),(91),(92),(93),(94),(95),(96),(97),(98),(99),(100),(101),(102),(103),(104),(105),(106),(107),(108),(109),(110),(111),(112),(113),(114),(115),(116),(117),(118),(119),(120),(121),(122),(123),(124),(125),(126),(127),(128),(129),(130),(131),(132),(133),(134),(135),(136),(137),(138),(139),(140),(141),(142),(143),(144),(145),(146),(147),(148),(149),(150),(151),(152),(153),(154),(155),(156),(157),(158),(159),(160),(161),(162),(163),(164),(165),(166),(167),(168),(169),(170),(171),(172),(173),(174),(175),(176),(177),(178),(179),(180),(181),(182),(183),(184),(185),(186),(187),(188),(189),(190),(191),(192),(193),(194),(195),(196),(197),(198),(199),(200),(201),(202),(203),(204),(205),(206),(207),(208),(209),(210),(211),(212),(213),(214),(215),(216),(217),(218),(219),(220),(221),(222),(223),(224),(225),(226),(227),(228),(229),(230),(231),(232),(233),(234),(235),(236),(237),(238),(239),(240),(241),(242),(243),(244),(245),(246),(247),(248),(249),(250),(251),(252),(253),(254),(255);
后,您可以使用它像:
select date_add(tbl.date, interval tinyint_asc.value day) as mydate, count(*), sum(myvalue)
from tbl inner join tinyint_asc.value <= 30 -- for a 30 day moving average
where date(date_add(o.created_at, interval tinyint_asc.value day)) between '2016-01-01' and current_date()
group by mydate
请问这个平均“搬家”? – Strawberry 2016-03-23 20:25:12
这只是一个静态平均值计算。运动的部分是每天计算。 – surfer190 2016-03-24 06:10:41