波峰是当日价格严格大于前一天和后一天价格,波谷是当日价格严格小于前一天和后一天价格;需用ORDER BY明确排序,配合LAG()和LEAD()获取邻值,用COALESCE处理边界NULL,且不可在WHERE中直接引用窗口结果。

怎么用 LAG() 和 LEAD() 判断波峰波谷
波峰波谷本质是局部极值:某行数值比前一行和后一行都大(波峰),或都小(波谷)。PostgreSQL 没有内置“找极值”函数,但 LAG() 和 LEAD() 可以安全获取相邻行值——前提是明确排序逻辑,否则结果无意义。
关键点:必须用 ORDER BY 定义窗口顺序,且该列需具备业务连续性(比如时间戳、序号)。若排序列有重复值,需加二级排序(如 ORDER BY ts, id)避免非确定性。
实操建议:
- 始终在
OVER (ORDER BY ...)中显式声明排序,不依赖表物理顺序 - 用
COALESCE()处理首尾行的NULL:首行无前驱,LAG()返回NULL;末行无后继,LEAD()同理 - 避免在
WHERE中直接过滤波峰波谷标记——窗口函数不能在WHERE中引用,得套一层子查询或 CTE
波峰波谷标记的 SQL 写法示例
假设有一张股票分钟级行情表 tick_data,含字段 ts(时间)、price(价格):
-INF
- 不适合高频抖动数据(如原始传感器噪声),需先平滑(移动平均)再分析
- 对等值平台(连续多行 price 相同)无法标记——严格定义下,平台既非波峰也非波谷;若需识别“平台顶/底”,得改用
MIN()/MAX()窗口聚合配合范围帧
对比前后行时容易忽略的边界与精度问题
浮点数比较必须小心。如果 price 是 NUMERIC 类型还好,若是 REAL 或 DOUBLE PRECISION,直接 > 可能因精度丢失导致误判。建议统一转为 NUMERIC 或用差值阈值判断:
ABS(price - LAG(price) OVER (ORDER BY ts)) > 0.001
另一个易忽略点:时间间隔不均。若 ts 缺失或跳跃大(如隔了 5 分钟才一条记录),用相邻行比较会漏掉中间真实波峰。此时应先用 GENERATE_SERIES() 补全时间序列,再插值或填充,否则分析结果反映的是采样偏差,不是真实走势。
复杂点永远在数据质量本身——窗口函数只是工具,它不会替你决定“多大算波动”“多久算趋势”。










