LEAD (Transact-SQL)

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例Azure Synapse AnalyticsAnalytics Platform System (PDW)Microsoft Fabric 中的 SQL 分析终结点Microsoft Fabric 中的仓库

访问相同结果集的后续行中的数据,而不使用 SQL Server 2012 (11.x) 开始提供的自联接。 LEAD 以当前行之后的给定物理偏移量来提供对行的访问。 在 SELECT 语句中使用此分析函数可将当前行中的值与后续行中的值进行比较。

Transact-SQL 语法约定

语法

LEAD ( scalar_expression [ , offset ] , [ default ] ) [ IGNORE NULLS | RESPECT NULLS ]
    OVER ( [ partition_by_clause ] order_by_clause )  

注意

若要查看 SQL Server 2014 (12.x) 及更早版本的 Transact-SQL 语法,请参阅早期版本文档

参数

scalar_expression

要根据指定偏移量返回的值。 这是一个返回单个(标量)值的任何类型的表达式。 scalar_expression 不能为分析函数

offset
从在其中获取值的当前行前移的行数。 如果未指定,则默认值为 1。 offset 可以是列、子查询或其他表达式,它们的计算值为正整数,或可隐式转换为 bigint。 offset 不能是负数值或分析函数

default
偏移量超出分区范围时返回的值。 如果未指定默认值,则返回 NULL。 default 可以是列、子查询或其他表达式,但它不能是分析函数default 的类型与 scalar_expression 的类型必须兼容。

[ IGNORE NULLS | RESPECT NULLS ]

适用范围:SQL Server(SQL Server 2022 (16.x) 及更高版本)、Azure SQL 数据库、Azure SQL 托管实例、Azure SQL Edge

IGNORE NULLS - 计算分区上的第一个值时,忽略数据集中的 NULL 值。

RESPECT NULLS - 计算分区上的第一个值时,考虑数据集中的 NULL 值。 如果未指定 NULLS 选项,RESPECT NULLS 是默认行为。

SQL Server 2022 CU4 中存在与 LAGLEAD 中的 IGNORE NULLS 相关的 Bug 修复。

有关 Azure SQL Edge 中此参数的详细信息,请参阅输入缺失值

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

LEAD 具有不确定性。 有关详细信息,请参阅 Deterministic and Nondeterministic Functions

示例

A. 比较年度之间的值

此查询使用 LEAD 函数返回特定员工在后续年度的销售配额差异。 请注意,因为最后一行没有提供提前值,所以将返回默认值零 (0)。

USE AdventureWorks2022;  
GO  
SELECT BusinessEntityID, YEAR(QuotaDate) AS SalesYear, SalesQuota AS CurrentQuota,   
    LEAD(SalesQuota, 1,0) OVER (ORDER BY YEAR(QuotaDate)) AS NextQuota  
FROM Sales.SalesPersonQuotaHistory  
WHERE BusinessEntityID = 275 AND YEAR(QuotaDate) IN ('2005','2006');  

下面是结果集:

BusinessEntityID SalesYear   CurrentQuota          NextQuota  
---------------- ----------- --------------------- ---------------------  
275              2005        367000.00             556000.00  
275              2005        556000.00             502000.00  
275              2006        502000.00             550000.00  
275              2006        550000.00             1429000.00  
275              2006        1429000.00            1324000.00  
275              2006        1324000.00            0.00  

B. 比较分区中的值

下面的示例使用 LEAD 函数比较员工之间年初至今的销售额。 指定 PARTITION BY 子句来按销售地区对结果集中的行进行分区。 LEAD 函数分别应用于每个分区,并为每个分区重新启动计算。 在应用函数之前,在 OVER 子句中指定的 ORDER BY 子句将对每个分区中的行进行排序。 SELECT 语句中的 ORDER BY 子句对整个结果集中的行进行排序。 请注意,因为每个分区的最后一行没有提供提前值,所以将返回默认值零 (0)。

USE AdventureWorks2022;  
GO  
SELECT TerritoryName, BusinessEntityID, SalesYTD,   
       LEAD (SalesYTD, 1, 0) OVER (PARTITION BY TerritoryName ORDER BY SalesYTD DESC) AS NextRepSales  
FROM Sales.vSalesPerson  
WHERE TerritoryName IN (N'Northwest', N'Canada')   
ORDER BY TerritoryName;  

下面是结果集。

TerritoryName            BusinessEntityID SalesYTD              NextRepSales  
-----------------------  ---------------- --------------------- ---------------------  
Canada                   282              2604540.7172          1453719.4653  
Canada                   278              1453719.4653          0.00  
Northwest                284              1576562.1966          1573012.9383  
Northwest                283              1573012.9383          1352577.1325  
Northwest                280              1352577.1325          0.00  
  

C. 指定任意表达式

下面的示例演示如何在 LEAD 函数语法中指定各种任意表达式和忽略 NULL 值。

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,   
    LEAD(2*c, b*(SELECT MIN(b) FROM T), -c/2.0) IGNORE NULLS OVER (ORDER BY a) AS i  
FROM T;  

下面是结果集。

b           c           i  
----------- ----------- -----------  
1           5           -2  
2           NULL        NULL  
3           1           0  
1           NULL        2  
2           4           2  
1           -3          8  

D. 使用 IGNORE NULLS 来查找非 NULL 值

以下示例查询演示了如何使用 IGNORE NULLS 参数。

IGNORE NULLS 参数与 LAG 和 LEAD 一起使用,用于演示前面或下面的非 NULL 值的 NULL 值的替换。

  • 如果前一行包含带有 LAG 的 NULL,则当前行使用最新的非 NULL 值。
  • 如果下一行包含带有 LEAD 的 NULL,则当前行使用下一个可用的非 NULL 值。
DROP TABLE IF EXISTS #test_ignore_nulls;
CREATE TABLE #test_ignore_nulls (column_a int, column_b int);
GO

INSERT INTO #test_ignore_nulls VALUES
    (1, 8),
    (2, 9),
    (3, NULL),
    (4, 10),
    (5, NULL),
    (6, NULL),
    (7, 11);

SELECT column_a, column_b,
      [Previous value for column_b] = LAG(column_b) IGNORE NULLS OVER (ORDER BY column_a),
      [Next value for column_b] = LEAD(column_b) IGNORE NULLS OVER (ORDER BY column_a)
FROM #test_ignore_nulls
ORDER BY column_a;

--cleanup
DROP TABLE #test_ignore_nulls;
column_a     column_b    Previous value for column_b    Next value for column_b
1            8           NULL                           9
2            9           8                              10
3            NULL        9                              10
4            10          9                              11
5            NULL        10                             11
6            NULL        10                             11
7            11          10                             NULL

E. 使用 RESPECT NULLS 来保留 NULL 值

下面的示例查询演示了如何使用 RESPECT NULLS 参数(如果未指定,这是默认行为),而不是上一示例中的 IGNORE NULLS 参数。

  • 如果前一行包含带有 LAG 的 NULL,则当前行使用最新的值。
  • 如果下一行包含带有 LEAD 的 NULL,则当前行使用下一个值。
DROP TABLE IF EXISTS #test_ignore_nulls;
CREATE TABLE #test_ignore_nulls (column_a int, column_b int);
GO

INSERT INTO #test_ignore_nulls VALUES
    (1, 8),
    (2, 9),
    (3, NULL),
    (4, 10),
    (5, NULL),
    (6, NULL),
    (7, 11);

SELECT column_a, column_b,
      [Previous value for column_b] = LAG(column_b) RESPECT NULLS OVER (ORDER BY column_a),
      [Next value for column_b] = LEAD(column_b) RESPECT NULLS OVER (ORDER BY column_a)
FROM #test_ignore_nulls
ORDER BY column_a;

--Identical output
SELECT column_a, column_b,
      [Previous value for column_b] = LAG(column_b)  OVER (ORDER BY column_a),
      [Next value for column_b] = LEAD(column_b)  OVER (ORDER BY column_a)
FROM #test_ignore_nulls
ORDER BY column_a;

--cleanup
DROP TABLE #test_ignore_nulls;
column_a     column_b    Previous value for column_b    Next value for column_b
1            8           NULL                           9
2            9           8                              NULL
3            NULL        9                              10
4            10          NULL                           NULL
5            NULL        10                             NULL
6            NULL        NULL                           11
7            11          NULL                           NULL

示例:Azure Synapse Analytics 和 Analytics Platform System (PDW)

A. 比较季度之间的值

以下示例演示了 LEAD 函数。 该查询可获得指定员工在后续各日历季度的销售配额值差异。 请注意,因为最后一行没有提供提前值,所以使用默认值零 (0)。

-- Uses AdventureWorks  
  
SELECT CalendarYear AS Year, CalendarQuarter AS Quarter, SalesAmountQuota AS SalesQuota,  
       LEAD(SalesAmountQuota,1,0) OVER (ORDER BY CalendarYear, CalendarQuarter) AS NextQuota,  
   SalesAmountQuota - LEAD(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  NextQuota  Diff  
---- -------  ----------  ---------  -------------  
2001 3        28000.0000   7000.0000   21000.0000 
2001 4         7000.0000  91000.0000  -84000.0000  
2001 1        91000.0000 140000.0000  -49000.0000  
2002 2       140000.0000   7000.0000    7000.0000  
2002 3         7000.0000 154000.0000   84000.0000  
2002 4       154000.0000      0.0000  154000.0000

后续步骤