LAG 是什么
LAG 取当前行之前第 N 行的值,是环比、差值、时间间隔计算的基础。它有两个默认行为:偏移量默认为 1 行,找不到前值时返回 NULL,两者都可以显式指定。它是窗口函数,必须带 OVER 子句,且计算发生在 WHERE 与 GROUP BY 之后。
基本信息
| 语法 | LAG(expr [, offset [, default]]) OVER (ORDER BY …) |
|---|---|
| 偏移量 | 省略时为 1;写 2 表示往前数两行 |
| 默认值 | 省略时首行返回 NULL,可显式指定为 0 之类 |
| 分区 | 常配合 PARTITION BY 做组内环比 |
| 配对函数 | LEAD 取下一行,方向相反,参数一致 |
| 计算时机 | 窗口函数在 WHERE / GROUP BY 之后执行,WHERE 里不能引用其结果 |
环比与差值
环比与差值
SELECT dt,
amount,
LAG(amount, 1) OVER (ORDER BY dt) AS prev_amount, -- 上一行金额
amount - LAG(amount, 1) OVER (ORDER BY dt) AS diff, -- 差额
ROUND(100.0 * (amount - LAG(amount, 1) OVER (ORDER BY dt))
/ NULLIF(LAG(amount, 1) OVER (ORDER BY dt), 0), 2) AS pct
FROM daily_sales
ORDER BY dt; -- 首行三列均为 NULL:没有前值可比组内环比与默认值
组内环比与默认值
SELECT store_id, month, revenue,
LAG(revenue, 1, 0) OVER (PARTITION BY store_id ORDER BY month) AS prev_rev
FROM store_monthly
WHERE month >= '2024-01-01'
ORDER BY store_id, month; -- 指定默认值 0:每个门店的首月不再返回 NULL参数与行为
| 要点 | 说明 | 注意事项 |
|---|---|---|
| offset | 往前第 N 行 | 超出行范围按“没有前值”处理 |
| default | 无前值时的返回值 | 不指定时为 NULL |
| PARTITION BY | 在每个分组内独立计算 | 漏写会让不同对象互相比较 |
| ORDER BY | 决定“上一行”是谁 | 排序键重复时前一行不确定 |
| 与 WHERE 关系 | 先过滤再开窗还是先开窗再过滤,结果不同 | 需要保留全量口径时包一层子查询 |
典型使用场景
- 环比同比:本期与上期金额相减、相除
- 相邻差值:库存变化、里程增量、传感器读数跳变
- 会话切分:用与上一条的时间间隔判断是否属于同一会话
- 排序后做条件判断,例如首次达到某个阈值的时点
- 在结果里直接给出对比列,省去 BI 层再做自连接
- 配合 LEAD 同时输出前后值,用于序列类数据的平滑判断
LAG 与 LEAD 是一对搭档:一个往前取、一个往后取,都严格依赖 ORDER BY。要拿“上一行”必须先有确定排序,否则结果每次执行都可能不同。
排序键有重复值或日期有缺口时,“上一行”不等于“上一个周期”。报表级环比要先补全日期序列,或在排序键后补主键作为次级排序,保证顺序确定。