LEAD()和LAG()仅返回值,不能直接判断趋势;需结合差值或比较运算(如sales > LEAD(sales,1))才能识别上升/下降方向。
直接用 LEAD() 或 LAG() 做趋势方向判断本身不靠谱——它只取值,不判断趋势;真正要识别“上升/下降”,得靠差值、符号或连续模式,而不是函数名本身。
LEAD/LAG 返回的只是值,不是趋势结论
很多人以为 LEAD(sales, 1) 拿到下一行销量,就能直接说“这是增长”,其实不是。它只返回一个数字,后续必须显式做比较才能得出方向:
-
sales > LEAD(sales, 1) OVER (ORDER BY date)→ 下降(当前比下一天高) sales → 上升(当前比下一天低)- 漏掉
OVER子句会报错,或被数据库当普通聚合处理,结果完全不可信 - 如果日期有空缺(比如跳过周末),
LEAD(sales, 1)拿的是“下一条记录”,不一定是“明天”,趋势标签就失真
用 CASE + 窗口差值判断单步趋势最稳妥
单次对比(日环比、月环比)推荐统一用 LAG() 计算前值再比,语义更清晰:
SELECT
date``,
sales_amount,
LAG(sales_amount) OVER (ORDER BY date``) AS prev_amount,
CASE
WHEN sales_amount > LAG(sales_amount) OVER (ORDER BY date``) THEN '↑'
WHEN sales_amount < LAG(sales_amount) OVER (ORDER BY date``) THEN '↓'
ELSE '→'
END AS trend
FROM daily_sales;
注意点:
- 必须给
LAG()加第三参数防 NULL,否则首行trend全是NULL:LAG(sales_amount, 1, 0) - 别在
CASE里重复写两遍LAG(),性能差且易出错;先用子查询或 CTE 提前算好prev_amount -
NULLIF(prev_amount, 0)要配合除法使用(如算增长率),但单纯判方向不需要
PARTITION BY 错位会导致趋势跨组污染
想按商品看各自趋势,却得到“所有商品混在一起排”的结果?大概率是 PARTITION BY product_id 写错了位置:
- 正确:
LAG(sales, 1) OVER (PARTITION BY product_id ORDER BY date) - 错误:
LAG(sales, 1) OVER (ORDER BY date) PARTITION BY product_id(语法非法) - 更隐蔽的错:把
PARTITION BY放在ORDER BY后面,部分数据库会静默忽略分区 - 如果
product_id有 NULL,所有 NULL 值会被归为同一组,导致多个商品趋势串在一起
omegafw.sepis.com.cn
rolexfw.sepis.com.cn
patekfw.sepis.com.cn
omega1.gmcwatch.cn
rolex1.gmcwatch.cn
patek1.gmcwatch.cn
omega1.swatchsh.com
rolex1.swatchsh.com
patek1.swatchsh.com
omegawx.paydyj.com
rolexwx.paydyj.com
patekwx.paydyj.com
omegawx.watchku.com
rolexwx.watchku.com
patekwx.watchku.com
连续多期趋势(如“连续3个月上升”)不能靠单个 LEAD/LAG 解决
单次 LEAD() 只能看一步,要识别单调序列,得结合行号与累计逻辑:
- 先用
LAG()算每期相对前一期的变化符号(+1 / -1 / 0) - 再用
SUM()窗口函数对符号做累加,找连续非负段 - 或者用
ROW_NUMBER() OVER (PARTITION BY product_id ORDER BY date)配合自连接,比用RANK()更可靠(避免同值跳号破坏连续性) - 补全时间维度仍是前提——没数据的月份不参与计算,就会把“断层”误认为“拐点”
真正难的从来不是写对一个 LEAD(),而是让时间对齐、分组干净、空值可控——这三处一错,趋势结论就全偏了。