MySQL中的累积和

时间:2017-05-17 09:45:46

标签: mysql sql

使用MySQL。我希望获得累计金额。

这是我的表

CREATE TABLE `user_infos`
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
(..)
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`) )

我想得到的是

+-------+-------+----------------+
| month | count | cumulative_sum |
+-------+-------+----------------+
|   01  |  100  | 100            |
|   02  |  101  | 201            |
|   ... |  110  | 311            |
|   12  |  200  | 511            |
+-------+-------+----------------+

但结果是

+-------+-------+----------------+
| month | count | cumulative_sum |
+-------+-------+----------------+
|   01  |  100  | 100            |
|   02  |  101  | 101            |
|   ... |  110  | 110            |
|   12  |  200  | 200            |
+-------+-------+----------------+

这是我的错误查询..

select 
     T1.Month,T1.Count,
     @runnung_total := (@running_total + T1.Count) as cumulative_sum
from (
     select date_format(created_at,'%m') as Month,count(1) as Count from users 
          where date_format(created_at,'%Y')='2016'
          group by(date_format(created_at,'%m'))
     union
     select date_format(created_at,'%m') as Month,count(1) as Count from users 
          where date_format(created_at,'%Y')='2017'
          group by(date_format(created_at,'%m')) ) as T1
join (select @running_total := 0) as R1;

我提到this。我的代码有什么问题?

3 个答案:

答案 0 :(得分:1)

您可以分两步完成:首先获得每年和每月的总和

select  concat(year(created_at), lpad(month(created_at), 2, '0')) as ye_mo,
        count(*) as cnt
from    users
group by concat(year(created_at), lpad(month(created_at), 2, '0'))

然后将其与自身连接,让每一行与之前的所有行匹配

select  t1.ye_mo, sum(t2.cnt)
from    (
            select  concat(year(created_at), lpad(month(created_at), 2, '0')) as ye_mo,
                    count(*) as cnt
            from    users
            group by concat(year(created_at), lpad(month(created_at), 2, '0'))
        ) t1
join    (
            select  concat(year(created_at), lpad(month(created_at), 2, '0')) as ye_mo,
                    count(*) as cnt
            from    users
            group by concat(year(created_at), lpad(month(created_at), 2, '0'))
        ) t2
on      t1.ye_mo >= t2.ye_mo
group by t1.ye_mo
order by t1.ye_mo

修改

上面的查询假设您希望不同年份的运行总和增加。如果您只想显示月份,并在同一个月汇总不同年份的值,您可以通过这种方式更改ID

select  t1.mnt, sum(t2.cnt)
from    (
            select  month(created_at) as mnt,
                    count(*) as cnt
            from    userss
            group by month(created_at)
        ) t1
join    (
            select  month(created_at) as mnt,
                    count(*) as cnt
            from    userss
            group by month(created_at)
        ) t2
on      t1.mnt >= t2.mnt
group by t1.mnt
order by t1.mnt

最后,如果您希望在每年年初重置运行总和,您可以这样做

select  t1.yr, t1.mn, sum(t2.cnt)
from    (
            select  year(created_at) as yr, month(created_at) as mn,
                    count(*) as cnt
            from    userss
            group by year(created_at), month(created_at)
        ) t1
join    (
            select  year(created_at) as yr, month(created_at) as mn,
                    count(*) as cnt
            from    userss
            group by year(created_at), month(created_at)
        ) t2
on      t1.yr = t2.yr and
        t1.mn >= t2.mn
group by t1.yr, t1.mn
order by t1.yr, t1.mn

可以在行动中看到所有三个版本 here

答案 1 :(得分:1)

变量是正确的方法。您可以简化查询:

select m.Month, m.cnt,
     (@running_total := (@running_total + m.cnt) ) as cumulative_sum
from (select month(created_at) as Month, count(*) as cnt
      from users 
      where year(created_at) in (2016, 2017)
      group by month(created_at)
     ) m cross join
     (select @running_total := 0) params
order by m.Month;

答案 2 :(得分:0)

从MySQL 8开始,理想的计算累计总和的方法是使用SQL标准window functions,而不是特定于供应商的方法,而不是严格声明性的使用局部变量的方法。您的查询可以编写如下:

WITH data(month, count) AS (
  SELECT date_format(create_at, '%m') AS month, count(*) AS count
  FROM users
  GROUP BY date_format(create_at, '%m')
)
SELECT
  month,
  count,
  sum(count) OVER (ORDER BY month) AS cumulative_sum
FROM data