从MySql中的月度数据计算移动平均值

时间:2016-10-10 10:07:22

标签: mysql moving-average

我想从MySql中的月度数据计算移动平均线。

我想使用每个team_id的前12个月的数据进行计算 平均销售的商品数量。

理想情况下,当特定月份遗失team_id时,我希望将该月包含为 0

另一个警告: 如果我们在October 2016,那么我希望移动平均窗口来自 September 2016September 2015

这是我的尝试不起作用:

SELECT t1.monthyear
     , t2.team_id
     , t1.itemssold
     , AVG(t2.itemssold) AS avgTransactions
  FROM t1
  JOIN t1 AS t2 
    ON PERIOD_DIFF(t2.monthyear,t1.monthyear) = 12 
   AND (t2.team_id = t1.team_id)
 GROUP 
    BY t1.team_id
     , monthyear;

一些数据:

monthyear   tmonth  tyear   team_id ItemsSold
201405  5   2014    23  1
201406  6   2014    23  3
201407  7   2014    23  5
201408  8   2014    23  3
201409  9   2014    23  7
201410  10  2014    23  1
201411  11  2014    23  4
201501  1   2015    23  6
201502  2   2015    23  2
201503  3   2015    23  2
201504  4   2015    23  5
201505  5   2015    23  5
201506  6   2015    23  6
201507  7   2015    23  11
201508  8   2015    23  13
201509  9   2015    23  5
201601  1   2016    23  14
201602  2   2016    23  4
201603  3   2016    23  3
201604  4   2016    23  10
201605  5   2016    23  9
201606  6   2016    23  7
201409  9   2014    83  1
201511  11  2015    83  1
201604  4   2016    83  4
201605  5   2016    83  1
201606  6   2016    83  3
201405  5   2014    88  1
201406  6   2014    88  3
201407  7   2014    88  4
201408  8   2014    88  3
201409  9   2014    88  6
201410  10  2014    88  7
201411  11  2014    88  5
201412  12  2014    88  11
201501  1   2015    88  8
201502  2   2015    88  5
201503  3   2015    88  6
201504  4   2015    88  3
201505  5   2015    88  11
201506  6   2015    88  6
201507  7   2015    88  12
201508  8   2015    88  14
201509  9   2015    88  11
201510  10  2015    88  12
201511  11  2015    88  14
201512  12  2015    88  13
201601  1   2016    88  7
201602  2   2016    88  10
201603  3   2016    88  15
201604  4   2016    88  11
201605  5   2016    88  14
201606  6   2016    88  10
201410  10  2014    131 2
201501  1   2015    131 1
201505  5   2015    131 1
201509  9   2015    131 2
201407  7   2014    135 2
201503  3   2015    135 1
201509  9   2015    135 1
201603  3   2016    135 1
201605  5   2016    135 1
201405  5   2014    140 15
201406  6   2014    140 18
201407  7   2014    140 14
201408  8   2014    140 21
201409  9   2014    140 22
201410  10  2014    140 19
201411  11  2014    140 18
201412  12  2014    140 13
201501  1   2015    140 25
201502  2   2015    140 17
201503  3   2015    140 26
201504  4   2015    140 17
201505  5   2015    140 14
201506  6   2015    140 16
201507  7   2015    140 20
201508  8   2015    140 17
201509  9   2015    140 23
201510  10  2015    140 19
201511  11  2015    140 12
201512  12  2015    140 4

1 个答案:

答案 0 :(得分:0)

如果你有类似这样的日期表

+------+------------+----------+------------------+-------------------+--------+
| id   | dte        | CalMonth | CalMonthDescLong | CalMonthDescShort | calQtr |
+------+------------+----------+------------------+-------------------+--------+
|    1 | 2000-01-01 |        1 | January          | Jan               |      1 |
|    2 | 2000-01-02 |        1 | January          | Jan               |      1 |
|    3 | 2000-01-03 |        1 | January          | Jan               |      1 |
|    4 | 2000-01-04 |        1 | January          | Jan               |      1 |
|    5 | 2000-01-05 |        1 | January          | Jan               |      1 |
+------+------------+----------+------------------+-------------------+--------+

您可以为缺少的日期生成虚拟条目,例如

select distinct year(dte) * 100 + month(dte)  monthyear, month(dte) as tmonth, year(dte) as tyear, t1.team_id,0 as itemssold
from   dates
cross join (select distinct t.team_id from t) t1 
where year(dte) * 100 + month(dte) >= (select min(monthyear) from t) and year(dte) * 100 + month(dte) <= (select max(monthyear) from t) 
        and t1.team_id = 23

将虚拟条目与实际数据合并,如此

select s.team_id,s.monthyear,s.tmonth,s.tyear,
        sum(case when s.itemssold is  null then 0 else s.itemssold end) itemsold 
from
(
select distinct year(dte) * 100 + month(dte)  monthyear, month(dte) as tmonth, year(dte) as tyear, t1.team_id,0 as itemssold
from   dates
cross join (select distinct t.team_id from t) t1 
where year(dte) * 100 + month(dte) >= (select min(monthyear) from t) and year(dte) * 100 + month(dte) <= (select max(monthyear) from t) 
        and t1.team_id = 23
union
select t.monthyear,t.tmonth,t.tyear,t.team_id,t.ItemsSold from t
) s
group by  s.team_id,s.monthyear,s.tmonth,s.tyear

然后将其加入另一个版本并计算出移动平均线

select t2.team_id,t2.monthyear,t2.itemsold
        ,sum(t3.itemsold) sold,count(*) obs
        ,AVG(t3.itemsold * 1.00) AS avgTransactions

from
(
select s.team_id,s.monthyear,s.tmonth,s.tyear,
        sum(case when s.itemssold is  null then 0 else s.itemssold end) itemsold 
from
(
select distinct year(dte) * 100 + month(dte)  monthyear, month(dte) as tmonth, year(dte) as tyear, t1.team_id,0 as itemssold
from   dates
cross join (select distinct t.team_id from t) t1 
where year(dte) * 100 + month(dte) >= (select min(monthyear) from t) and year(dte) * 100 + month(dte) <= (select max(monthyear) from t) 
        #and t1.team_id = 23
union
select t.monthyear,t.tmonth,t.tyear,t.team_id,t.ItemsSold from t
) s
group by  s.team_id,s.monthyear,s.tmonth,s.tyear
) t2
join
(
select s.team_id,s.monthyear,s.tmonth,s.tyear,
        sum(case when s.itemssold is  null then 0 else s.itemssold end) itemsold 
from
(
select distinct year(dte) * 100 + month(dte)  monthyear, month(dte) as tmonth, year(dte) as tyear, t1.team_id,0 as itemssold
from   dates
cross join (select distinct t.team_id from t) t1 
where year(dte) * 100 + month(dte) >= (select min(monthyear) from t) and year(dte) * 100 + month(dte) <= (select max(monthyear) from t) 
        #and t1.team_id = 23
union
select t.monthyear,t.tmonth,t.tyear,t.team_id,t.ItemsSold from t
) s
group by  s.team_id,s.monthyear,s.tmonth,s.tyear
) t3
on t2.team_id = t3.team_id and (t3.tyear * 12 + t3.tmonth  between (t2.tyear * 12 + t2.tmonth) - 11  and (t2.tyear * 12 + t2.tmonth))
group by t2.team_id,t2.monthyear desc

(部分)结果

+---------+-----------+----------+------+-----+-----------------+
| team_id | monthyear | itemsold | sold | obs | avgTransactions |
+---------+-----------+----------+------+-----+-----------------+
|      23 |    201606 |        7 |   76 |  12 |        6.333333 |
|      23 |    201605 |        9 |   75 |  12 |        6.250000 |
|      23 |    201604 |       10 |   71 |  12 |        5.916667 |
|      23 |    201603 |        3 |   66 |  12 |        5.500000 |
|      23 |    201602 |        4 |   65 |  12 |        5.416667 |
|      23 |    201601 |       14 |   63 |  12 |        5.250000 |
|      23 |    201512 |        0 |   55 |  12 |        4.583333 |
|      23 |    201511 |        0 |   55 |  12 |        4.583333 |
|      23 |    201510 |        0 |   59 |  12 |        4.916667 |
|      23 |    201509 |        5 |   60 |  12 |        5.000000 |
|      23 |    201508 |       13 |   62 |  12 |        5.166667 |
|      23 |    201507 |       11 |   52 |  12 |        4.333333 |
|      23 |    201506 |        6 |   46 |  12 |        3.833333 |
|      23 |    201505 |        5 |   43 |  12 |        3.583333 |
|      23 |    201504 |        5 |   39 |  12 |        3.250000 |
|      23 |    201503 |        2 |   34 |  11 |        3.090909 |
|      23 |    201502 |        2 |   32 |  10 |        3.200000 |
|      23 |    201501 |        6 |   30 |   9 |        3.333333 |
|      23 |    201412 |        0 |   24 |   8 |        3.000000 |
|      23 |    201411 |        4 |   24 |   7 |        3.428571 |
|      23 |    201410 |        1 |   20 |   6 |        3.333333 |
|      23 |    201409 |        7 |   19 |   5 |        3.800000 |
|      23 |    201408 |        3 |   12 |   4 |        3.000000 |
|      23 |    201407 |        5 |    9 |   3 |        3.000000 |
|      23 |    201406 |        3 |    4 |   2 |        2.000000 |
|      23 |    201405 |        1 |    1 |   1 |        1.000000 |
|      83 |    201606 |        3 |    9 |  12 |        0.750000 |
|      83 |    201605 |        1 |    6 |  12 |        0.500000 |