LAG (Transact-SQL)
适用于:SQL Server
Azure SQL 数据库
Azure SQL 托管实例
Azure Synapse Analytics
Analytics Platform System (PDW)
Microsoft Fabric 中的 SQL 终结点
Microsoft Fabric 中的仓库
访问相同结果集中先前行的数据,而不使用 SQL Server 2012 (11.x) 开始提供的自联接。 LAG 以当前行之前的给定物理偏移量来提供对行的访问。 在 SELECT 语句中使用此分析函数可将当前行中的值与先前行中的值进行比较。
语法
LAG (scalar_expression [,offset] [,default])
OVER ( [ partition_by_clause ] order_by_clause )
注意
若要查看 SQL Server 2014 及更早版本的 Transact-SQL 语法,请参阅早期版本文档。
参数
scalar_expression
要根据指定偏移量返回的值。 这是一个返回单个(标量)值的任何类型的表达式。 scalar_expression 不能为分析函数。
offset
当前行(从中获得取值)后的行数。 如果未指定,则默认值为 1。 offset 可以是列、子查询或其他表达式,它们的计算值为正整数,或可隐式转换为 bigint。 offset 不能是负数值或分析函数。
default
偏移量超出分区范围时返回的值。 如果未指定默认值,则返回 NULL。 default 可以是列、子查询或其他表达式,但它不能是分析函数。 default 的类型与 scalar_expression 的类型必须兼容。
OVER ( [ partition_by_clause ] order_by_clause)
partition_by_clause 将 FROM 子句生成的结果集划分为要应用函数的分区 。 如果未指定,则此函数将查询结果集的所有行视为单个组。 order_by_clause 在应用函数之前确定数据的顺序 。 当指定 partition_by_clause 时,它确定分区中数据的顺序。 需要 order_by_clause 。 有关详细信息,请参阅 OVER 子句 (Transact-SQL)。
返回类型
指定 scalar_expression 的数据类型。 如果 scalar_expression 可以为 null 或 default 被设置为 NULL,则返回 NULL。
一般备注
LAG 具有不确定性。 有关详细信息,请参阅 Deterministic and Nondeterministic Functions。
示例
A. 比较年度之间的值
以下示例使用 LAG 函数返回特定员工前几年的销售配额差异。 请注意,因为第一行没有提供滞后值,所以将返回默认值零 (0)。
USE AdventureWorks2012;
GO
SELECT BusinessEntityID, YEAR(QuotaDate) AS SalesYear, SalesQuota AS CurrentQuota,
LAG(SalesQuota, 1,0) OVER (ORDER BY YEAR(QuotaDate)) AS PreviousQuota
FROM Sales.SalesPersonQuotaHistory
WHERE BusinessEntityID = 275 AND YEAR(QuotaDate) IN ('2005','2006');
下面是结果集:
BusinessEntityID SalesYear CurrentQuota PreviousQuota
---------------- ----------- --------------------- ---------------------
275 2005 367000.00 0.00
275 2005 556000.00 367000.00
275 2006 502000.00 556000.00
275 2006 550000.00 502000.00
275 2006 1429000.00 550000.00
275 2006 1324000.00 1429000.00
B. 比较分区中的值
下面的示例使用 LAG 函数比较员工之间年初至今的销售额。 指定 PARTITION BY 子句来按销售地区对结果集中的行进行划分。 LAG 函数分别应用于每个分区,并为每个分区重新启动计算。 OVER 子句中的 ORDER BY 子句对每个分区中的行进行排序。 SELECT 语句中的 ORDER BY 子句对整个结果集中的行进行排序。 请注意,因为每个分区的第一行没有提供滞后值,所以将返回默认值零 (0)。
USE AdventureWorks2012;
GO
SELECT TerritoryName, BusinessEntityID, SalesYTD,
LAG (SalesYTD, 1, 0) OVER (PARTITION BY TerritoryName ORDER BY SalesYTD DESC) AS PrevRepSales
FROM Sales.vSalesPerson
WHERE TerritoryName IN (N'Northwest', N'Canada')
ORDER BY TerritoryName;
下面是结果集。
TerritoryName BusinessEntityID SalesYTD PrevRepSales
----------------------- ---------------- --------------------- ---------------------
Canada 282 2604540.7172 0.00
Canada 278 1453719.4653 2604540.7172
Northwest 284 1576562.1966 0.00
Northwest 283 1573012.9383 1576562.1966
Northwest 280 1352577.1325 1573012.9383
C. 指定任意表达式
下面的示例演示如何在 LAG 函数语法中指定各种任意表达式。
CREATE TABLE T (a INT, b INT, c INT);
GO
INSERT INTO T VALUES (1, 1, -3), (2, 2, 4), (3, 1, NULL), (4, 3, 1), (5, 2, NULL), (6, 1, 5);
SELECT b, c,
LAG(2*c, b*(SELECT MIN(b) FROM T), -c/2.0) OVER (ORDER BY a) AS i
FROM T;
下面是结果集。
b c i
----------- ----------- -----------
1 -3 1
2 4 -2
1 NULL 8
3 1 -6
2 NULL NULL
1 5 NULL
示例:Azure Synapse Analytics 和 Analytics Platform System (PDW)
D:比较季度之间的值
以下示例演示了 LAG 函数。 该查询使用 LAG 函数返回特定员工前几个日历季度的销售配额差异。 请注意,因为第一行没有提供滞后值,所以将返回默认值零 (0)。
-- Uses AdventureWorks
SELECT CalendarYear, CalendarQuarter, SalesAmountQuota AS SalesQuota,
LAG(SalesAmountQuota,1,0) OVER (ORDER BY CalendarYear, CalendarQuarter) AS PrevQuota,
SalesAmountQuota - LAG(SalesAmountQuota,1,0) OVER (ORDER BY CalendarYear, CalendarQuarter) AS Diff
FROM dbo.FactSalesQuota
WHERE EmployeeKey = 272 AND CalendarYear IN (2001, 2002)
ORDER BY CalendarYear, CalendarQuarter;
下面是结果集。
Year Quarter SalesQuota PrevQuota Diff
---- ------- ---------- --------- -------------
2001 3 28000.0000 0.0000 28000.0000
2001 4 7000.0000 28000.0000 -21000.0000
2001 1 91000.0000 7000.0000 84000.0000
2002 2 140000.0000 91000.0000 49000.0000
2002 3 7000.0000 140000.0000 -70000.0000
2002 4 154000.0000 7000.0000 84000.0000