lag函数自sql server 2012(11.x)起原生支持,此前版本不识别该函数;即使实例为2012+,若数据库兼容级别低于110(如设为100),仍会报错;sql server 2022及azure sql新增ignore nulls选项,但cu4前存在bug;必须配合order by使用,分组需显式指定partition by,否则逻辑错误。

SQL Server 2012 是 LAG 函数的起始支持版本
LAG 函数从 SQL Server 2012 (11.x) 开始原生支持,此前版本(如 2008 R2 或更早)无法直接使用该函数。如果你在低版本 SQL Server 上执行 LAG(),会收到类似 ‘LAG’ is not a recognized built-in function name. 的错误。
检查当前数据库兼容性级别是否达标
即使 SQL Server 实例是 2012 或更高版本,如果数据库的兼容性级别被手动设为低于 110(例如 100 对应 SQL Server 2008),LAG() 仍不可用。
- 运行
SELECT compatibility_level FROM sys.databases WHERE name = DB_NAME();查看当前值 - 低于
110就必须升级:执行ALTER DATABASE [your_db] SET COMPATIBILITY_LEVEL = 110; - 注意:
ALTER DATABASE会清空计划缓存,可能短暂影响查询性能
LAG 在 Azure SQL 和较新版本中的扩展行为
SQL Server 2022(16.x)及 Azure SQL 数据库支持 IGNORE NULLS 选项,但该功能在 SQL Server 2022 CU4 之前存在 Bug;若需稳定使用此特性,建议确认补丁版本或改用 ROW_NUMBER() + 子查询模拟。
-
LAG(col, 1, 0) OVER (ORDER BY ts)—— 第三个参数0是默认值,仅在偏移超出范围时生效 -
LAG(col) OVER (PARTITION BY user_id ORDER BY ts)—— 缺少PARTITION BY会导致跨用户混算,这是最常被忽略的逻辑错误 - 排序字段
ts必须具有确定性;若时间戳重复,建议追加唯一列如id防止结果不稳定
替代方案:没有 LAG 时怎么模拟前一行取值
在不支持 LAG() 的旧环境(如 SQL Server 2008),只能靠自联接或相关子查询,但性能和可读性都差很多。
- 典型写法:
LEFT JOIN t AS prev ON curr.date = DATEADD(day, 1, prev.date)—— 前提是日期连续,节假日场景会断裂 - 更健壮的子查询:
(SELECT TOP 1 ClosePrice FROM MicrosiftStockHistory m2 WHERE m2.StockDate - 这类写法在大表上极易产生嵌套循环,务必确保
StockDate有索引
LAG() 能自动处理业务语义——比如“上一个交易日”不等于“物理上一行”,它只认 ORDER BY 定义的顺序,而这个顺序是否贴合业务,得你来保证。










