在SQL Server中使用LAG()和LEAD()函数时是否可以忽略NULL值?

时间:2014-06-21 03:56:05

标签: sql sql-server-2012

如你所知LAG()& LEAD()分析函数在不使用自联接的情况下从同一结果集中的上一行和下一行访问数据。但是在访问NOT NULL值之前是否可以忽略NULL值?

3 个答案:

答案 0 :(得分:5)

可以使用窗口函数。 请阅读Itzik Ben-Gan的这篇article了解更多详情。

在下面的代码中,cte获取最新的NOT NULL id值,然后下一个select获取实际的列值。此示例使用LAG。 例如

-- DDL for T1
SET NOCOUNT ON;
USE tempdb;
IF OBJECT_ID(N'dbo.T1', N'U') IS NOT NULL DROP TABLE dbo.T1;
GO
CREATE TABLE dbo.T1
(
id INT NOT NULL CONSTRAINT PK_T1 PRIMARY KEY,
col1 INT NULL
);

-- Small set of sample data
TRUNCATE TABLE dbo.T1;

INSERT INTO dbo.T1(id, col1) VALUES
( 2, NULL),
( 3,   10),
( 5,   -1),
( 7, NULL),
(11, NULL),
(13,  -12),
(17, NULL),
(19, NULL),
(23, 1759);

;WITH C AS
(
SELECT
    id, 
    col1, 
    MAX(CASE WHEN col1 IS NOT NULL THEN id END) OVER(ORDER BY id ROWS UNBOUNDED PRECEDING) AS grp
FROM dbo.T1
)
SELECT
    id, 
    col1, 
    (SELECT col1 FROM dbo.T1 WHERE id = grp) lastval    
FROM C;

答案 1 :(得分:0)

Oracle 11支持选项ignore nulls,它完全符合您的要求。当然,您的问题是关于SQL Server,但有时令人振奋的是知道功能确实存在于某个地方。

可以模拟此功能。我们的想法是根据前面的值为组分配空值。实质上,这是计算它之前的非空值的数量。您可以使用相关子查询执行此操作。或者,更有趣的是,两个行号的差异。然后在组内,您可以使用max()

我认为以下是您想要的。假设col包含NULL个值,而ordering包含行的排序:

select t.*,
       max(col) over (partition by grp) as LagOnNull
from (select t.*,
             (row_number() over (order by ordering) - 
              row_number() over (partition by col order by ordering)
             ) as grp
      from table t
     ) t;

lead()类似,但顺序相反。而且,这将与其他分区键一起使用,但您需要将它们添加到所有窗口表达式中。

答案 2 :(得分:-1)

LEAD(IIF(col1 IS NULL,NULL, col1),1) OVER PARTITION BY (ISNULL(col1))