lag()配合时间差函数(如postgresql的extract、mysql的timestampdiff)计算相邻记录时间间隔,超业务阈值即判定为断点;需显式order by、处理首行null、统一时区与精度,并依数据特征动态设定阈值。

用LAG()和时间差判断相邻记录是否断开
断点本质是时间序列中相邻两条记录的时间间隔超过预期阈值。核心思路是用 LAG() 取上一行时间戳,再计算差值。注意不同数据库对时间差函数的写法差异很大:PostgreSQL 用 EXTRACT(EPOCH FROM (current_time - prev_time)),MySQL 用 TIMESTAMPDIFF(SECOND, prev_time, current_time),SQL Server 用 DATEDIFF(second, prev_time, current_time)。
常见错误是直接用减法(如 time - LAG(time)),这在多数数据库会报错或返回不可靠结果。必须显式调用时间差函数。
- 设定合理阈值:比如传感器每5秒一条数据,就设阈值为10秒,容忍短暂延迟
- 确保数据按时间排序:
ORDER BY time ASC必须出现在窗口函数的OVER()子句里 - 首条记录的
LAG()返回 NULL,需用WHERE diff IS NOT NULL AND diff > threshold过滤
处理不等间隔采样下的断点识别
当原始数据本身就不等间隔(比如用户主动上报、事件触发采集),不能简单用固定阈值。此时要先估算“典型间隔”,再定义异常倍数。常用做法是用 PERCENTILE_CONT(0.5) 或 AVG() 计算中位数/均值间隔,再设为基准。
例如:先用子查询算出中位间隔 med_interval,主查询中判断 diff > med_interval * 3。注意 PERCENTILE_CONT 在 PostgreSQL 和 SQL Server 中支持,在 MySQL 8.0+ 需用变量模拟。
- 避免用
AVG()代替中位数——离群大间隔会严重拉高均值 - 分组识别时加
PARTITION BY device_id,防止不同设备间干扰 - 时间字段类型必须一致:
TIMESTAMP和DATETIME混用可能导致隐式转换误差
修复断点后补全缺失时间点(可选)
识别出断点只是第一步,有时需要生成中间缺失的时间点。纯 SQL 补全依赖递归 CTE 或生成序列函数:generate_series()(PostgreSQL)、RECURSIVE CTE(SQL Server、SQLite)、numbers table(MySQL)。但要注意性能——跨度大的断点会生成大量行。
更务实的做法是只补关键区间:先用断点位置确定起止时间范围,再限制生成最多1000行。例如用 generate_series(start_time, end_time, INTERVAL '5 second'),其中 start_time 和 end_time 来自断点前后两条记录。
- 补全后需
LEFT JOIN原表,保留真实数据优先,NULL 表示真正缺失 - 避免在大表上无条件全量补全,容易 OOM 或超时
-
INTERVAL单位必须与原始采样单位一致,别把分钟写成秒
断点识别的关键不在函数多炫酷,而在阈值是否贴合业务节奏、时间计算是否跨数据库兼容、以及是否考虑了数据本身的不规则性。最容易被忽略的是时间字段的时区和精度——TIMESTAMP WITH TIME ZONE 和 TIMESTAMP 混查,或者毫秒级数据用秒级函数比较,都会让断点判断完全失效。











