LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

同比、环比、累计值,这几个常见分析 SQL 写法一次讲明白

admin
2026年4月13日 22:50 本文热度 13

做数据分析,最常见也最容易说混的三个词,就是:同比、环比、累计值。

很多人平时都在用,但一到自己写 SQL 就容易乱:到底该跟谁比、在哪个粒度上比、什么时候该先聚合、什么时候该上窗口函数。

这一篇不整虚的,直接把这三个概念和最常见 SQL 写法讲透。

一、先把概念讲人话

1. 同比

同比,就是和去年同期比。

比如:

  • • 2026 年 3 月销售额,对比 2025 年 3 月销售额
  • • 今天订单量,对比去年今天订单量

同比适合看长期趋势,尤其适合有季节性的业务。

2. 环比

环比,就是和上一个统计周期比。

比如:

  • • 本月对比上月
  • • 今天对比昨天
  • • 本周对比上周

环比适合看短期变化和拐点。

3. 累计值

累计值,就是从起点开始一直往后加,到当前为止。

比如:

  • • 截至今天累计销售额
  • • 本月截至今天累计订单量
  • • 今年累计收入

累计值适合看进度和总量。

二、写 SQL 之前,先确定粒度

假设有一张订单明细表:

create table orders (
  order_id   bigint,
  user_id    bigint,
  order_date date,
  amount     decimal(18,2)
);

如果你要看按月销售额,就先按月聚合,不要拿明细直接硬算。

with month_gmv as (
  select
    date_trunc('month', order_date) as month_dt,
    sum(amount) as gmv
  from orders
  group by 1
)
select *
from month_gmv
order by month_dt;

这一点特别重要:先聚合到目标粒度,再做同比、环比、累计。

三、同比 SQL 怎么写

写法一:lelf join 去年同期

这是最稳的一种写法。

with month_gmv as (
  select
    date_trunc('month', order_date) as month_dt,
    sum(amount) as gmv
  from orders
  group by 1
)
select
  a.month_dt,
  a.gmv as curr_gmv,
  b.gmv as last_year_gmv,
  a.gmv - b.gmv as yoy_diff,
  case
    when b.gmv is null or b.gmv = 0 then null
    else (a.gmv - b.gmv) / b.gmv
  end as yoy_rate
from month_gmv a
left join month_gmv b
  on a.month_dt = b.month_dt + interval '1 year'
order by a.month_dt;

同比增长率公式就是:

本期减去年同期,再除以去年同期。

写法二:用 lag 取去年同月

如果你的时间序列是连续的,也可以直接用窗口函数。

with month_gmv as (
  select
    date_trunc('month', order_date) as month_dt,
    sum(amount) as gmv
  from orders
  group by 1
)
select
  month_dt,
  gmv,
  lag(gmv, 12) over(order by month_dt) as last_year_gmv,
  case
    when lag(gmv, 12) over(order by month_dt) is null
      or lag(gmv, 12) over(order by month_dt) = 0 then null
    else (gmv - lag(gmv, 12) over(order by month_dt))
         / lag(gmv, 12) over(order by month_dt)
  end as yoy_rate
from month_gmv
order by month_dt;

如果中间有缺月,lag 可能会错位。这种情况下,还是 self join 更稳。

四、环比 SQL 怎么写

环比本质上就是和上一期比较。

with month_gmv as (
  select
    date_trunc('month', order_date) as month_dt,
    sum(amount) as gmv
  from orders
  group by 1
)
select
  month_dt,
  gmv,
  lag(gmv, 1) over(order by month_dt) as prev_gmv,
  case
    when lag(gmv, 1) over(order by month_dt) is null
      or lag(gmv, 1) over(order by month_dt) = 0 then null
    else (gmv - lag(gmv, 1) over(order by month_dt))
         / lag(gmv, 1) over(order by month_dt)
  end as mom_rate
from month_gmv
order by month_dt;

别把“环比”理解得太窄。它不只是月环比,而是当前周期和上一周期比。

五、累计值 SQL 怎么写

累计值最常见的写法就是窗口函数 sum over。

比如按天累计销售额:

with day_gmv as (
  select
    order_date,
    sum(amount) as gmv
  from orders
  group by order_date
)
select
  order_date,
  gmv,
  sum(gmv) over(
    order by order_date
    rows between unbounded preceding and current row
  ) as cumulative_gmv
from day_gmv
order by order_date;

如果要算年累计,就按年份分区。

sum(gmv) over(
  partition by extract(year from order_date)
  order by order_date
  rows between unbounded preceding and current row
)

如果要算月累计,就按月份分区。

六、最容易翻车的几个坑

1. 粒度没对齐

嘴上说按月同比,SQL 却拿天级数据直接 lag(12)。这不是去年同月,是前 12 天。

2. 时间序列不连续

lag 取的是前 N 行,不是自动帮你找去年同期。缺月时很容易错位。

3. 分母为 0

同比、环比分母为 0 时,SQL 层建议返回 null,展示层再决定怎么显示。

4. 对明细直接做累计

累计前应该先按目标粒度聚合,否则得到的是逐行累计,不是按天或按月累计。

5. 去重指标先算再比

像 DAU、MAU、付费用户数这种去重指标,应该先按周期聚合出结果,再做同比或环比。

七、到底什么时候该看哪个指标

如果你想看长期趋势,用同比。

如果你想看最近有没有变好变差,用环比。

如果你想看当前进度和总体规模,用累计值。

现实工作里,三者通常一起看。

老板最爱的一句通常是:给我看下本月收入、环比、同比,还有年累计。

嗯,经典四件套,跑不掉。

八、最后记住这四句话

  1. 1. 同比 = 和去年同期比
  2. 2. 环比 = 和上一周期比
  3. 3. 累计值 = 从起点加到当前
  4. 4. 先按目标粒度聚合,再做同比、环比、累计

很多 SQL 问题,表面看是函数不会写,实际上是粒度错了、口径歪了、时间轴没补齐。

语法问题一般几分钟修完,口径问题能让你和业务扯一下午。

别给自己找这个罪受。


阅读原文:原文链接


该文章在 2026/4/14 16:12:48 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved  粤ICP备13012886号-2  粤公网安备44030602007207号