How about this ?
select id ,last_value(date1 ignore nulls) over ( order by id rows between unbounded preceding and current row ) date1 ,first_value(date2 ignore nulls) over ( order by id rows between current row and unbounded following ) date2
You can also manually calculate this, rather than relying on window functions.
with chain as ( select this.*, prev.date1 prev_date1, case when prev.date1 is not null then abs(this.id - prev.id) else null end prev_distance, next.date2 next_date2, case when next.date2 is not null then abs(this.id - next.id) else null end next_distance from Table1 this left outer join Table1 prev on this.id >= prev.id left outer join Table1 next on this.id <= next.id ), min_distance as ( select id, min(prev_distance) min_prev_distance, min(next_distance) min_next_distance from chain group by id ) select chain.id, chain.prev_date1, chain.next_date2 from chain join min_distance on min_distance.id = chain.id and chain.prev_distance = min_distance.min_prev_distance and chain.next_distance = min_distance.min_next_distance order by chain.id
If you cannot calculate the distance between the identifiers by subtracting, simply replace the ordering scheme with row_number() .
source share