我正在使用 SQL Server 2016,我正在使用的数据具有以下形式。
CREATE TABLE #tab (cat CHAR(1), t CHAR(2), val1 INT, val2 CHAR(1));
INSERT INTO #tab VALUES
('A','Q1',2,NULL),('A','Q2',NULL,'P'),('A','Q3',1,NULL),('A','Q3',NULL,NULL),
('B','Q1',5,NULL),('B','Q2',NULL,'P'),('B','Q3',NULL,'C'),('B','Q3',10,NULL);
SELECT *
FROM #tab;
我想获得列上的最后一个非空值,val1
并按val2
分组cat
和排序t
。我正在寻找的结果是
cat val1 val2 A 1 P B 10 C
我最接近的是使用LAST_VALUE
,而忽略ORDER BY
which 不起作用,因为我需要排序的最后一个非空值。
SELECT DISTINCT
cat,
LAST_VALUE(val1) OVER(PARTITION BY cat ORDER BY (SELECT NULL) ) AS val1,
LAST_VALUE(val2) OVER(PARTITION BY cat ORDER BY (SELECT NULL) ) AS val2
FROM #tab
cat val1 val2 A NULL NULL B 10 NULL
实际的表有更多的列cat
(日期和字符串列)和更多的 val 列(日期、字符串和数字列)来选择最后一个非空值。
任何想法如何进行此选择。
使用Itzik Ben Gan的 The Last non NULL Puzzle中的连接技术与您的示例表和列数据类型看起来像这样。
编写此查询的另一种方法是将步骤划分为 CTE,以便更好地显示正在发生的事情。它给出了与上面的查询完全相同的执行计划。
此解决方案使用了将空值与某些内容连接会导致空值的事实。SET CONCAT_NULL_YIELDS_NULL (Transact-SQL)
只需在分区中添加对 NULL 的检查即可
这应该这样做。row_number() 和一个连接
如果你没有一个好的排序,你必须希望 Q3 中只有一个不是空的。