老生常谈,指标不是孤立的,必须有对比才有意义,环比和同比就是将当前的指标值与过往的指标值进行对比,从而表明当前的指标值是好是坏。环比是跟上一个周期比(周期通常是月或周),同比是跟历史同期比(周期通常是年),区分环比和同比主要看时间周期是否连续,比如,今天比昨天、本周比上周、本月比上月都是环比,本周二比上周二、2021年3月比2019年3月都是同比,2020年全年比2019年全年既是同比也是环比,通常称为同比。

理清楚环比同比的作用和概念后,我们再来看看 SQL环比同比 的实现。假设我们已有如下的销售明细表sales:

  • 统计每类产品的每月销售总额并计算环比同比:

示例代码:

--方法1:计算环比同比所对应的周期, 然后匹配计算
with
--1:按产品+月份分组汇总
    tmp1 as (
        select
            product,
            date_trunc('month', order_date) as order_month,
            sum(amount) as amount
        from sales
        group by 1,2
    ),

--2:计算环比同比所对应的月份
    tmp2 as (
        select
            product,
            order_month,
            date_trunc('month', order_month - interval '1' day) as bef_1M_month,
            order_month - interval '12' month as bef_1Y_month,
            amount
        from tmp1
    ),

--3:匹配环比同比所对应的值
    tmp3 as (
        select
            t1.product,
            t1.order_month,
            t1.amount,
            t2.amount as bef_1M_month_amount,
            t3.amount as bef_1Y_month_amount
        from tmp2 as t1
        left join tmp1 as t2
        on t1.product = t2.product and t1.bef_1M_month = t2.order_month
        left join tmp1 as t3
        on t1.product = t3.product and t1.bef_1Y_month = t3.order_month
    )

--4:计算环比同比
select
    product,
    order_month,
    amount,
    round((amount - bef_1M_month_amount)/bef_1M_month_amount,4) as ratio_month_on_month,
    round((amount - bef_1Y_month_amount)/bef_1Y_month_amount,4) as ratio_year_on_year
from tmp3
order by 1,2;



--方法2:使用lag()窗口函数获取环比同比所对应的值,然后计算
--仅当数据中的时间周期是连续的不缺失的时候才可使用此方法
with
--1:按产品+月份分组汇总
    tmp1 as (
        select
            product,
            date_trunc('month', order_date) as order_month,
            sum(amount) as amount
        from sales
        group by 1,2
    ),
 
--2:使用lag()窗口函数获取环比同比所对应的值
    tmp2 as (
        select
            product,
            order_month,
            amount,
            lag(amount,1) over (partition by product order by order_month) as bef_1M_month_amount,
            lag(amount,12) over (partition by product order by order_month) as bef_1Y_month_amount
        from tmp1
    )

--3:计算环比同比
select
    product,
    order_month,
    amount,
    round((amount - bef_1M_month_amount)/bef_1M_month_amount,4) as ratio_month_on_month,
    round((amount - bef_1Y_month_amount)/bef_1Y_month_amount,4) as ratio_year_on_year
from tmp2
order by 1,2;

代码结果:

以上就是 SQL环比同比 的实现,使用Presto SQL执行,其他SQL在日期处理上可能会有差异。 能够看出,方法1的通用性更强,在周期是连续的不缺失的情况下,方法2更简洁高效,我们可视源数据情况选用方法1或方法2。 为便于展示处理逻辑,示例代码以分步的形式进行处理,实际取数时可以对中间的步骤进行合并,以便提高效率。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注