首页/数据/SQL 速查/环比计算(与上期对比)
聚合与窗口函数54 条

环比计算(与上期对比)

用 LAG 取上一期值算环比:注意分区(门店/品类)与排序(月份)要写全,否则跨对象对比会出错。

SQL 速查数据更新于 2026-10-13

环比计算是什么

用 LAG 取上一期的值,与本期相减或相除就得到环比。关键是分区与排序要写全:分区键决定“和谁比”(同一门店、同一品类),排序键决定“跟哪一期比”。任意一个写漏,都会算出看起来合理却完全错误的结果。

基本信息

核心写法LAG(值) OVER (PARTITION BY 对象 ORDER BY 时间)
分区PARTITION BY 业务对象,例如门店、商品
排序ORDER BY 时间,例如月份、日期
首期处理没有上一期,结果为 NULL,需要单独说明
除零保护分母用 NULLIF 包住
时间缺口序列不连续时“上一行”不等于“上一期”

门店月度环比

门店月度环比
SELECT store_id, month, revenue,
       LAG(revenue) OVER (PARTITION BY store_id ORDER BY month) AS prev_revenue,
       ROUND(100.0 * (revenue - LAG(revenue) OVER (PARTITION BY store_id ORDER BY month))
             / NULLIF(LAG(revenue) OVER (PARTITION BY store_id ORDER BY month), 0), 2) AS mom_pct
FROM store_monthly
ORDER BY store_id, month;
-- 各门店首行 prev_revenue 为 NULL,环比自然为空
-- 上期为 0 时返回 NULL,而不是报错

常见错误与后果

写法结果正确做法
漏掉 PARTITION BY不同门店互相比较,环比全错按业务对象分区
漏掉 ORDER BY没有“上一期”的定义,结果不确定按时间排序
月份有缺口和上一条记录比,而不是上一个月先补全月份序列
未防除零分母为 0 时报错或返回 NULL分母套 NULLIF
首期不处理首行显示异常或空白单独过滤或补默认值

典型使用场景

  • 门店月度营收环比,用于经营分析
  • 商品销量周环比,识别增长或下滑趋势
  • 接口调用量日环比,用于容量预警
  • 用户活跃数环比,评估运营活动效果
  • 环比与同比并列展示:环比看短期波动,同比看年度趋势
  • 数据校验:环比异常大的值往往是补数或口径变化造成的
补全日期序列是算环比的前提:某个月缺数据时 LAG 会取到更早的月份,环比就成了跨期比较。常见做法是先构造连续月份序列,再左连接业务数据。
环比值域没有上限:上期很小而本期很大时会得到几百甚至几千个百分点的增长,报表直接展示容易误导。必要时同时给出绝对值,或对超过一定幅度的值做标记。

易错点

  • 漏写 PARTITION BY:不同门店相互比较,环比结果完全错误
  • 月份有缺失仍直接计算:变成跨期比较,增长幅度失真,先补全时间序列
  • 分母为 0 未保护:上期为 0 时无法计算增长率,用 NULLIF 返回 NULL 并单独说明
  • 首期不做处理:第一行环比为空,展示时要注明“无上期数据”而不是显示异常值

数据来源与参考

  • MySQL 8.0 Reference Manual · LAG
  • PostgreSQL Documentation · Window Functions
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌