是否在PostgreSQL中实现了最后一次观察结转(LOCF)?

是否在PostgreSQL中实现了最后一次观察结转(LOCF)?,postgresql,missing-data,Postgresql,Missing Data,数据插补方法上次观察结转()是否在PostgreSQL中实现?如果没有,我如何实现此方法?我将此表和数据直接基于链接文章中的表 create table test ( unit integer not null check (unit >= 1), obs_time integer not null check (obs_time >= 1), obs_value numeric(5, 1), primary key (unit, obs_time)

数据插补方法上次观察结转()是否在PostgreSQL中实现?如果没有,我如何实现此方法?

我将此表和数据直接基于链接文章中的表

create table test (
  unit integer not null
    check (unit >= 1),
  obs_time integer not null
    check (obs_time >= 1),
  obs_value numeric(5, 1),
  primary key (unit, obs_time)
);

insert into test values
(1, 1, 3.8), (1, 2, 3.1), (1, 3, 2.0),
(2, 1, 4.1), (2, 2, 3.5), (2, 3, 3.8), (2, 4, 2.4), (2, 5, 2.8), (2, 6, 3.0),
(3, 1, 2.7), (3, 2, 2.4), (3, 3, 2.9), (3, 4, 3.5);
对于链接文章中的六个观察,我们需要“单位”和“obs_时间”的所有可能组合

单位obs_时间obs_值 -- 1 1 3.8 1 2 3.1 1 3 2.0 1 4 2.0 1 5 2.0 1 6 2.0 2 1 4.1 . . . 3 4 3.5 3 5 3.5 3 6 3.5
要获得与链接文章显示的相同的视觉输出,请在中使用crosstab()函数。您也可以使用应用程序代码进行操作。

我将此表和数据直接基于链接文章中的表

create table test (
  unit integer not null
    check (unit >= 1),
  obs_time integer not null
    check (obs_time >= 1),
  obs_value numeric(5, 1),
  primary key (unit, obs_time)
);

insert into test values
(1, 1, 3.8), (1, 2, 3.1), (1, 3, 2.0),
(2, 1, 4.1), (2, 2, 3.5), (2, 3, 3.8), (2, 4, 2.4), (2, 5, 2.8), (2, 6, 3.0),
(3, 1, 2.7), (3, 2, 2.4), (3, 3, 2.9), (3, 4, 3.5);
对于链接文章中的六个观察,我们需要“单位”和“obs_时间”的所有可能组合

单位obs_时间obs_值 -- 1 1 3.8 1 2 3.1 1 3 2.0 1 4 2.0 1 5 2.0 1 6 2.0 2 1 4.1 . . . 3 4 3.5 3 5 3.5 3 6 3.5
要获得与链接文章显示的相同的视觉输出,请在中使用crosstab()函数。您也可以使用应用程序代码执行该操作。

以下代码假定一个表
tbl
,其中包含列
a
b
(键)、
t
(时间)和
v
(locf插补值):

()



对于教程:

以下代码假设一个表
tbl
,其中包含
a
b
(键)、
t
(时间)和
v
(locf输入值):

()



对于教程:

为什么不
合并(obs_值,最后一个(obs_值)在无界前后行之间(按单位顺序按obs_时间划分)
?因为该表达式不起作用。(最后一个_value()函数在本例中的作用与您认为的不同。如果要使用窗口函数,需要重写它。)我编写了CREATE TABLE和INSERT语句;你自己试试。为什么不
在无界前后行之间(按单位顺序按obs\U时间划分)合并(obs\U值,最后一个值(obs\U值)
?因为该表达式不起作用。(最后一个_value()函数在本例中的作用与您认为的不同。如果要使用窗口函数,需要重写它。)我编写了CREATE TABLE和INSERT语句;你自己试试看。 unit obs_time -- 1 1 1 2 1 3 1 4 1 5 1 6 2 1 . . . 3 6
select unit, max(obs_time) obs_time
from test
group by unit
order by unit;
unit obs_time -- 1 3 2 6 3 4
with unit_times as (
  select distinct unit, times.obs_time 
  from test
  cross join (select generate_series(1, 6) obs_time) times
), last_obs_time as (
  select unit, max(obs_time) obs_time
  from test
  group by unit
)
select t1.unit, t1.obs_time, 
       coalesce(t2.obs_value, (select obs_value 
                               from test 
                               inner join last_obs_time 
                                  on test.unit = last_obs_time.unit 
                                 and test.obs_time = last_obs_time.obs_time 
                               where test.unit = t1.unit)) obs_value
from unit_times t1
left join test t2 
       on t1.unit = t2.unit and t1.obs_time = t2.obs_time
order by t1.unit, t1.obs_time;
unit obs_time obs_value -- 1 1 3.8 1 2 3.1 1 3 2.0 1 4 2.0 1 5 2.0 1 6 2.0 2 1 4.1 . . . 3 4 3.5 3 5 3.5 3 6 3.5
create or replace function locf_s(a float, b float)
returns float
language sql
as '
  select coalesce(b, a)
';

drop aggregate if exists locf(float);
CREATE AGGREGATE locf(FLOAT) (
  SFUNC = locf_s,
  STYPE = FLOAT
);

select a,b,t,v,
    locf(v) over (PARTITION by a,b ORDER by t) as v_locf
from tbl
order by a,b,t
;