【问题标题】:MySQL calculate yoy (year-over-year) dataMySQL 计算 yoy(同比)数据
【发布时间】:2018-01-25 07:09:50
【问题描述】:

我有一些每月粒度的 MAU 数据,如下所示:

我想得到像:

2016-04 yoy MAU = (2016-04 MAU - 2015-04 MAU)/2015-04 MAU  
2016-03 yoy MAU = (2016-03 MAU - 2015-03 MAU)/2015-03 MAU
...

我使用的是 MySQL,所以我没有窗口功能。 有没有更简单的方法来实现我想要的?

*数据类型:

Period                       | varchar(16)  
MAU                          | double  

【问题讨论】:

  • 这里有适合您的解决方案。
  • YOY MAU 英文版?
  • 你试过我提供的解决方案了吗?
  • @CKChen,你看过这个解决方案了吗?我在几分钟前添加了一个解释。
  • 为什么句号是字符串?

标签: mysql sql etl


【解决方案1】:

理想情况下,周期性数据将存储为日期或其组成部分,在这种情况下,年和月作为单独的整数列。由于它们在这里一起表示为一个字符串,因此我们需要使用 SUBSTRING 来解析它们。该解决方案背后的总体思路是,我们需要使用 ON 子句将表连接到自身,该子句将每一行与一年前的对应行“对齐”。

这应该可以解决问题:

select a.Period, a.MAU, b.Period as prior_year, b.MAU as prior_mau,
        (a.MAU - b.MAU) / b.MAU as yoy
    from tbl1 a
    left join tbl1 b on 
        cast(substring(b.Period, 1, 4) as int) = 
        cast(substring(a.Period, 1, 4) as int) - 1 
        and substring(b.Period, 5, 3) = substring(a.Period, 5, 3)   
    order by a.Period asc

这是第二种方式,虽然读起来不太清晰,但效率更高(尤其是在速度问题、表很大并且在 Period 上建立索引的情况下),因为它避免了 where 子句中的计算(至少在一个边):

select a.Period, a.MAU, b.Period as prior_year, b.MAU as prior_mau,
        (a.MAU - b.MAU) / b.MAU as yoy
    from tbl1 a
    left join tbl1 b on 
        a.Period 
        = cast(cast(substring(b.Period, 1, 4) as int) - 1 as varchar(4)) 
        + substring(b.Period, 5, 3)   
    order by a.Period asc

我希望这会有所帮助。

【讨论】:

  • 假设 period 被索引,你最好在减去一年后重新组合这两个部分。这样你就可以做到b.period = (calculation)
  • 是的@MatBailie,你是绝对正确的。我实际上考虑将 ON 测试的一侧保持在其原始形式(可以说,SQL 必须逐行逐行执行的计算),但选择了更多的视觉清晰度取而代之的是对称代码。考虑到数据的每月性质,表格的长度可能不是问题。你知道,我想我会继续将其添加为选项 2(尽管在这一点上,这家伙似乎永远不会回头看看是否有人回答了他的问题)。
猜你喜欢
  • 2013-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-22
  • 1970-01-01
  • 1970-01-01
  • 2013-08-18
  • 1970-01-01
相关资源
最近更新 更多