最常见的原因是没写 order by 子句,或排序字段存在重复值导致窗口无法确定“上一行”;lag 严格依赖 over (order by ...) 的逻辑顺序,而非物理存储顺序。

用 LAG 计算环比增长率时,为什么结果全是 NULL
最常见的原因是没写 ORDER BY 子句,或排序字段存在重复值导致窗口无法确定“上一行”。LAG 不是按物理存储顺序取值,而是严格依赖 OVER (ORDER BY ...) 定义的逻辑顺序。
实操建议:
- 确保
ORDER BY字段在分组内唯一(例如用date或year_month,避免只用year) - 显式指定偏移量和默认值:
LAG(sales, 1, 0) OVER (PARTITION BY region ORDER BY year_month) - 如果原始数据有缺失月份,先用
GENERATE_SERIES(PostgreSQL)或日期维表补全,再计算,否则LAG会跳过空档直接取更早的值
同比 vs 环比:LAG 的偏移量怎么设才对
环比看相邻周期(如本月 vs 上月),同比看相同周期的上年(如 2024-05 vs 2023-05)。偏移量不是固定写 1,而取决于你的时间粒度和数据组织方式。
关键判断点:
- 若数据按月存储且
year_month是202301,202302…格式,环比用LAG(val, 1),同比必须用LAG(val, 12) - 若用
DATE类型字段(如sale_date),推荐先生成标准周期标识:TO_CHAR(sale_date, 'YYYY-MM')或YEAR(sale_date)*100 + MONTH(sale_date),再PARTITION BY region ORDER BY ym,避免因天数差异导致错位 - 注意时区和业务日历——有些行业用财年(4月起始),此时同比偏移不是 12,而是 12 或 13,得按实际财年映射表对齐
分组后算增长率,PARTITION BY 放错位置会怎样
PARTITION BY 决定了“谁跟谁比”。放错会导致跨组污染:比如按 region 分组,但漏写 PARTITION BY region,那么北京的 2024-05 就可能和上海的 2024-04 比,结果完全失真。
典型错误场景:
- 只写
ORDER BY date,没写PARTITION BY category→ 所有品类混在一起排序,LAG取到的是前一品类的值 -
PARTITION BY包含了不该分的维度,例如多加了store_id→ 每个门店单独算,失去区域聚合意义 - 在聚合后又分组:先
GROUP BY region, year_month得到汇总值,再套窗口函数时,PARTITION BY必须与聚合维度一致,否则窗口无法对齐
增长率公式里除零和负基数怎么处理
直接写 (cur - prev) / prev 在 prev = 0 或 prev 为负数时,会得到 NULL(除零)或符号反直觉的结果(例如从 -100 到 50,增长率为 -150%)。
稳妥做法:
- 用
NULLIF(prev, 0)避免除零:(cur - prev) / NULLIF(prev, 0) - 对负基数场景,明确业务定义:是否允许负增长率为正?多数报表选择限制输入,即只对
prev > 0的组计算,其他标为NULL或'N/A' - 强制保留小数位并转百分比:
ROUND(((cur - prev)::NUMERIC / NULLIF(prev, 0) * 100), 2),注意类型强转,避免整数除法截断
实际跑通的关键,往往卡在时间字段的标准化和 PARTITION BY 维度的精确匹配上。很多“结果不对”的问题,回溯发现只是 ORDER BY 的字段少了一个 DESC,或者补全月份时没把 region 也纳入关联条件。










