【发布时间】:2014-06-21 03:56:05
【问题描述】:
如您所知,LAG() 和 LEAD() 分析函数可以访问同一结果集中的前一行和下一行的数据,而无需使用自联接。但是在访问 NOT NULL 值之前是否可以忽略 NULL 值?
【问题讨论】:
标签: sql sql-server-2012
如您所知,LAG() 和 LEAD() 分析函数可以访问同一结果集中的前一行和下一行的数据,而无需使用自联接。但是在访问 NOT NULL 值之前是否可以忽略 NULL 值?
【问题讨论】:
标签: sql sql-server-2012
可以使用窗口函数。 阅读 Itzik Ben-Gan 的 article 了解更多详情。
在下面的代码中,cte 获取最新的 NOT NULL id 值,然后下一个选择获取实际列值。此示例使用 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;
【讨论】:
Update: 来源文章网址:https://www.itprotoday.com/sql-server/last-non-null-puzzle
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() 类似,但顺序相反。而且,这将与其他分区键一起使用,但您需要将它们添加到所有窗口表达式中。
【讨论】:
col2 应该是 col,lag()/lead() 的参数。
NULLs 的lag() 1(我应该在答案中提到)。如果它对您不起作用,您应该使用您尝试过的查询来编辑您的问题。您必须在各种分析函数上正确使用分区子句。
LEAD(IIF(col1 IS NULL,NULL, col1),1) OVER PARTITION BY (ISNULL(col1))
【讨论】: