据我了解,您希望获取 id 分区中每个时间戳的先前不同日期。然后我会申请lag
反对独特的组合id
and date
并像这样连接回原始数据集:
with dat as (
select 1 as id,'20150101 02:02:50'::timestamp as dt union all
select 1,'20150101 03:02:50'::timestamp union all
select 1,'20150101 04:02:50'::timestamp union all
select 1,'20150102 02:02:50'::timestamp union all
select 1,'20150102 02:02:50'::timestamp union all
select 1,'20150102 02:02:51'::timestamp union all
select 1,'20150103 02:02:50'::timestamp union all
select 2,'20150101 02:02:50'::timestamp union all
select 2,'20150101 03:02:50'::timestamp union all
select 2,'20150101 04:02:50'::timestamp union all
select 2,'20150102 02:02:50'::timestamp union all
select 1,'20150104 02:02:50'::timestamp
)
,dat_unique_lag as (
select *, lag(date) over(partition by id order by date asc) prev_diff_value
from (
select distinct id,trunc(dt) as date
from dat
)
)
select *
from dat
join dat_unique_lag
using (id)
where trunc(dat.dt)=dat_unique_lag.date
order by id,dt desc;
然而,这并不是超级性能。如果您的数据的性质是同一天的时间戳数量有限,您可能只需使用如下条件语句来延长滞后:
with dat as (
select 1 as id,'20150101 02:02:50'::timestamp as dt union all
select 1,'20150101 03:02:50'::timestamp union all
select 1,'20150101 04:02:50'::timestamp union all
select 1,'20150102 02:02:50'::timestamp union all
select 1,'20150102 02:02:50'::timestamp union all
select 1,'20150102 02:02:51'::timestamp union all
select 1,'20150103 02:02:50'::timestamp union all
select 2,'20150101 02:02:50'::timestamp union all
select 2,'20150101 03:02:50'::timestamp union all
select 2,'20150101 04:02:50'::timestamp union all
select 2,'20150102 02:02:50'::timestamp union all
select 1,'20150104 02:02:50'::timestamp
)
select id, dt,
case
when lag(trunc(dt)) over(partition by id order by dt asc)=trunc(dt)
then case
when lag(trunc(dt),2) over(partition by id order by dt asc)=trunc(dt)
then case
when lag(trunc(dt),3) over(partition by id order by dt asc)=trunc(dt)
then lag(trunc(dt),4) over(partition by id order by dt asc)
else lag(trunc(dt),3) over(partition by id order by dt asc)
end
else lag(trunc(dt),2) over(partition by id order by dt asc)
end
else lag(trunc(dt)) over(partition by id order by dt asc)
end as prev_diff_value
from dat
order by id,dt desc;
基本上,您查看上一条记录,如果它不适合您,那么您会回头查看该记录之前的记录,依此类推,直到找到正确的记录或超出您的语句深度。在这里查看直到返回第四条记录。