【问题标题】:Calculating Cumulative values using MySQL使用 MySQL 计算累积值
【发布时间】:2017-03-30 17:44:00
【问题描述】:

我有这张桌子:

Month_Year              MV                    MI
----------------------------------------------------------
August 2016              3                    100
October 2016             2                    150
September 2016           1                    100
January 2017             4                    200

我需要创建下一个输出表

Month_Year               MV       AMV          MI     AMI
----------------------------------------------------------
January 2016             0        0            0      0
...
July 2016                0        0            0      0 
August 2016              3        3           100    100
September 2016           1        4           100    200
October 2016             2        6           150    350
November 2016            0        6           0      350
December 2016            0        6           0      350
January 2017             4        10          200    550

在 M 月,对于 AMV 列,AMV 是该月和 M 月之前所有 AV 的累积值。例如,“2016 年 9 月”的 AMV 为 4,因为在“8 月 16 日”,AV 为 3 和 1对于“2016 年 9 月”。 AMI 也是如此。如何才能做到这一点?。请注意,Month_Year 列不一定是有序的。谢谢

附加信息 使用 DATE_FORMAT(original_Date, '%Y %m') 后,我能够将第一个表转换为:

Month_Year              MV                    MI
----------------------------------------------------------
2016 08                  3                    100
2016 10                  2                    150
2016 09                  1                    100
2017 01                  4                    200

这可以简化问题吗?为什么不使用 DATE_FORMAT(original_Date, '%m %Y')?

【问题讨论】:

  • 我认为 Month_Year 对订购毫无用处的事实是你的错。该表应该有一个年份列和一个月份列,两者都包含数字。如果您希望结果查询将月份转换为单词,则通过外键使用表连接。一旦你有了一个模糊合理的模式,剩下的就很容易了。
  • 嗯,客户需要“month_year”格式,所以我尝试提供它。我使用命令: DATE_FORMAT(OrigDate, '%M %Y') 来获取月份年份字符串。我也在考虑使用其他按月份排序的其他表
  • 我刚刚更改了获取月份年份 DATE_FORMAT(origDate, '%m %Y') 的命令,所以现在我有了字符串“08 2016”、“09 2016”、“10 2016”。这个问题现在能解决吗?
  • 这简化了问题,但是我已经给你一个原始的、更复杂的公式的答案。你检查了吗?
  • 它显示了 2016 年 1 月的非零值......无论如何......你的算法看起来很有趣。谢谢

标签: mysql select


【解决方案1】:

月-年格式是一个很大的问题,您必须以某种方式克服它。在这个例子中,我创建了一个 MEMORY 表 months,并且我对这个表使用了几个连接。

create table months (month_year_int int, month_year varchar(30)) engine=memory;
insert months 
select 201601 as month_year_int, 'January 2016' as month_year
      union all select 201602, 'February 2016'
      union all select 201603, 'March 2016'
      union all select 201604, 'April 2016'
      union all select 201605, 'May 2016'
      union all select 201606, 'June 2016'
      union all select 201607, 'July 2016'
      union all select 201608, 'August 2016'
      union all select 201609, 'September 2016'
      union all select 201610, 'October 2016'
      union all select 201611, 'November 2016'
      union all select 201612, 'December 2016'
      union all select 201701, 'January 2017'
;

如果您为数据使用了合适的模型,所有这些都可以避免。无论如何,这是一个不使用 My-Sql 专有变量模式的解决方案(rextester demo here):

select 
    x.month_year, 
    coalesce(t.mv, 0) MV, 
    sum(y.mv) as AMV, 
    coalesce(t.mi, 0) AMV, 
    sum(y.mi) as AMI from 
(
    select 
        m.month_year_int, 
        m.month_year, 
        coalesce(t.mv, 0) as mv, 
        coalesce(t.mi) as mi
    from months m left join test t on m.month_year = t.month_year 
) x 
left join 
(
    select 
        m.month_year_int, 
        m.month_year, 
        coalesce(t.mv, 0) as mv, 
        coalesce(t.mi) as mi
    from months m
        left join test t on m.month_year = t.month_year 
) y on x.month_year_int > y.month_year_int - 1
left join test t on x.month_year = t.month_year
group by x.month_year_int
order by x.month_year_int
;

【讨论】:

  • 似乎最后一个 union all select 201701, 'January 2016' 应该是 union all select 201701, 'January 2017'
  • 谢谢,更新!
猜你喜欢
  • 2019-06-06
  • 2021-06-19
  • 2018-03-26
  • 2020-07-18
  • 2020-12-17
  • 2020-11-04
  • 2021-07-21
  • 1970-01-01
  • 2012-06-19
相关资源
最近更新 更多