不确定问这个问题的正确词语,所以我会分解它。
我有一个表格如下:
date_time | a | b | c
最后 4 行:
15/10/2013 11:45:00 | null | 'timtim' | 'fred'
15/10/2013 13:00:00 | 'tune' | 'reco' | null
16/10/2013 12:00:00 | 'abc' | null | null
16/10/2013 13:00:00 | null | 'died' | null
我如何获取最后一条记录,但值忽略空值,而是从前一条记录中获取值。
在我提供的示例中,返回的行将是
16/10/2013 13:00:00 | 'abc' | 'died' | 'fred'
如您所见,如果某列的值为 null,则它会转到具有该列值的最后一条记录并使用该值。
这应该是可能的,我就是想不通。到目前为止,我只想出了:
select
last_value(a) over w a
from test
WINDOW w AS (
partition by a
ORDER BY ts asc
range between current row and unbounded following
);
但这只适合单列...
最佳答案
在这里,我创建了一个聚合函数,用于将列收集到数组中。然后只需删除 NULL 并从每个数组中选择最后一个元素即可。
示例数据
CREATE TABLE T (
date_time timestamp,
a text,
b text,
c text
);
INSERT INTO T VALUES ('2013-10-15 11:45:00', NULL, 'timtim', 'fred'),
('2013-10-15 13:00:00', 'tune', 'reco', NULL ),
('2013-10-16 12:00:00', 'abc', NULL, NULL ),
('2013-10-16 13:00:00', NULL, 'died', NULL );
解决方案
CREATE AGGREGATE array_accum (anyelement)
(
sfunc = array_append,
stype = anyarray,
initcond = '{}'
);
WITH latest_nonull AS (
SELECT MAX(date_time) As MaxDateTime,
array_remove(array_accum(a), NULL) AS A,
array_remove(array_accum(b), NULL) AS B,
array_remove(array_accum(c), NULL) AS C
FROM T
ORDER BY date_time
)
SELECT MaxDateTime, A[array_upper(A, 1)], B[array_upper(B,1)], C[array_upper(C,1)]
FROM latest_nonull;
结果
maxdatetime | a | b | c
---------------------+-----+------+------
2013-10-16 13:00:00 | abc | died | fred
(1 row)
关于sql - 检索一行中每一列的最后一个已知值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20246242/