SQL 用最后观察到的值填充 nan
Posted
技术标签:
【中文标题】SQL 用最后观察到的值填充 nan【英文标题】:SQL fill nan with last observed value 【发布时间】:2021-04-25 10:56:48 【问题描述】:编写 SQL 查询,用最后一个已知值填充 Value 列 NaN。 SQLite
client_id | date | value |
---|---|---|
1 | 14.04.2020 | 10000 |
1 | 15.04.2020 | 5000 |
1 | 16.04.2020 | NaN |
1 | 17.04.2020 | NaN |
1 | 18.04.2020 | NaN |
2 | 14.04.2020 | 250000 |
2 | 15.04.2020 | 250000 |
2 | 16.04.2020 | 230000 |
2 | 17.04.2020 | 230000 |
2 | 18.04.2020 | 225000 |
3 | 14.04.2020 | 50000 |
3 | 15.04.2020 | NaN |
3 | 16.04.2020 | NaN |
我正在考虑窗口函数,但不知道如何在这里应用它。
【问题讨论】:
用您正在使用的数据库标记您的问题。 【参考方案1】:我从 'NaN'
的使用猜测你正在使用 Postgres。
不幸的是,Postgres 不支持窗口函数上的IGNORES NULL
选项。一种方法是为数字分配一个组,然后为该组估算值:
select t.*,
max(nullif(value, 'NaN')) over (partition by grp) as imputed_value
from (select t.*,
count(value) filter (where value <> 'NaN') over (partition by client_id order by date) as grp
from t
) t
也可以在不使用数组的子查询的情况下执行此操作,但表达式相当复杂:
select t.*,
(array_remove(array_agg(value)over (partition by client_id order by date), 'NaN'))[cardinality(array_remove(array_agg(value)over (partition by client_id order by date), 'NaN'))]
from t;
或者使用横向连接:
select t.*, t2.value as imputed_value
from t cross join lateral
(select t2.value
from t t2
where t2.client_id = t.client_id and
t2.date <= t.date and
t2.value <> 'NaN'
order by t2.date desc
limit 1
) t2;
Here 是一个 dbfiddle。
【讨论】:
不错。但是当您添加多个 client_id 时,第一种方法会出错。另外,我使用 SQLite 来完成这项任务,而不是 Postgres,我忘了说。以上是关于SQL 用最后观察到的值填充 nan的主要内容,如果未能解决你的问题,请参考以下文章
填写一列日期值,直到达到另一个日期值,然后继续填充新达到的值