Oracle SQL,用最接近的非缺失值填充缺失值
Oracle SQL, fill missing value with the closest non-missing
我有一个数据集,我想用最接近的非缺失值填充其中的缺失值。我在 this 问题的答案中找到了两个优雅的解决方案,但我不明白为什么它们对我不起作用。
Table:
create table Tab1(data date, V1 number);
insert into Tab1 values (date '2000-01-01', 1);
insert into Tab1 values (date '2000-02-01', 1);
insert into Tab1 values (date '2000-03-01', 1);
insert into Tab1 values (date '2000-04-01', 1);
insert into Tab1 values (date '2000-05-01', NULL);
insert into Tab1 values (date '2000-06-01', NULL);
insert into Tab1 values (date '2000-03-01', 2);
insert into Tab1 values (date '2000-04-01', 2);
insert into Tab1 values (date '2000-05-01', NULL);
insert into Tab1 values (date '2000-06-01', NULL);
select * from Tab1;
DATA V1
2000-01-01 1
2000-02-01 1
2000-03-01 1
2000-04-01 1
2000-05-01
2000-06-01
2000-03-01 2
2000-04-01 2
2000-05-01
2000-06-01
尝试 #1:
select A.*,
(case when V1 is null then lag(V1 ignore nulls)
over (partition by V1 order by V1, data)
else V1
end) V2
from Tab1 A;
尝试 #2:
select A.*,
(case when V1 is null
then last_value(V1 ignore nulls)
over (partition by V1 order by data
range between unbounded preceding and 1 preceding)
else V1
end) V2
from Tab1 A;
两者都给我相同的不需要的结果:
DATA V1 V2
2000-01-01 1 1
2000-02-01 1 1
2000-03-01 1 1
2000-04-01 1 1
2000-03-01 2 2
2000-04-01 2 2
2000-05-01
2000-05-01
2000-06-01
我做错了什么?
你的第一个版本应该可以工作,稍作调整:
select A.*,
coalesce(V1, lag(V1 ignore nulls) over (order by data)) V2
from Tab1 A;
调整是从 lag()
中删除 partition by v1
。 coalesce()
只是我对更简单表达式的偏爱。
同样的调整也适用于第二个版本。
您的版本不起作用,因为 lag()
值必须来自同一分区(或者是 null
)。当您有 partition by v1
时,您实际上是在确保 v1
与当前行中的值相同。
您好,或者您可以参考我的下文尝试手动创建忽略空值的解决方案。谢谢
- 您需要使用 0/1 列来表示 Null/Non-Null 数据
- 然后创建累积摘要列以计算步骤 1 中的指标编号。-现在您可以看到数据看起来已经按 non_Null 数据分组。
- 作为最后一步,请使用 Max 函数组通过累加和(在步骤 2 中)将数据(这里是 amont)填充到空项目中。
我有一个数据集,我想用最接近的非缺失值填充其中的缺失值。我在 this 问题的答案中找到了两个优雅的解决方案,但我不明白为什么它们对我不起作用。
Table:
create table Tab1(data date, V1 number);
insert into Tab1 values (date '2000-01-01', 1);
insert into Tab1 values (date '2000-02-01', 1);
insert into Tab1 values (date '2000-03-01', 1);
insert into Tab1 values (date '2000-04-01', 1);
insert into Tab1 values (date '2000-05-01', NULL);
insert into Tab1 values (date '2000-06-01', NULL);
insert into Tab1 values (date '2000-03-01', 2);
insert into Tab1 values (date '2000-04-01', 2);
insert into Tab1 values (date '2000-05-01', NULL);
insert into Tab1 values (date '2000-06-01', NULL);
select * from Tab1;
DATA V1
2000-01-01 1
2000-02-01 1
2000-03-01 1
2000-04-01 1
2000-05-01
2000-06-01
2000-03-01 2
2000-04-01 2
2000-05-01
2000-06-01
尝试 #1:
select A.*,
(case when V1 is null then lag(V1 ignore nulls)
over (partition by V1 order by V1, data)
else V1
end) V2
from Tab1 A;
尝试 #2:
select A.*,
(case when V1 is null
then last_value(V1 ignore nulls)
over (partition by V1 order by data
range between unbounded preceding and 1 preceding)
else V1
end) V2
from Tab1 A;
两者都给我相同的不需要的结果:
DATA V1 V2
2000-01-01 1 1
2000-02-01 1 1
2000-03-01 1 1
2000-04-01 1 1
2000-03-01 2 2
2000-04-01 2 2
2000-05-01
2000-05-01
2000-06-01
我做错了什么?
你的第一个版本应该可以工作,稍作调整:
select A.*,
coalesce(V1, lag(V1 ignore nulls) over (order by data)) V2
from Tab1 A;
调整是从 lag()
中删除 partition by v1
。 coalesce()
只是我对更简单表达式的偏爱。
同样的调整也适用于第二个版本。
您的版本不起作用,因为 lag()
值必须来自同一分区(或者是 null
)。当您有 partition by v1
时,您实际上是在确保 v1
与当前行中的值相同。
您好,或者您可以参考我的下文尝试手动创建忽略空值的解决方案。谢谢
- 您需要使用 0/1 列来表示 Null/Non-Null 数据
- 然后创建累积摘要列以计算步骤 1 中的指标编号。-现在您可以看到数据看起来已经按 non_Null 数据分组。
- 作为最后一步,请使用 Max 函数组通过累加和(在步骤 2 中)将数据(这里是 amont)填充到空项目中。