create function first_nonnull( one anyelement, two anyelement ) returns anyelement as $$ begin return one; end $$ language plpgsql strict; create function last_nonnull( one anyelement, two anyelement ) returns anyelement as $$ begin return two; end $$ language plpgsql strict; create aggregate first_nonnull( anyelement ) ( stype = anyelement , sfunc = first_nonnull ); create aggregate last_nonnull( anyelement ) ( stype = anyelement , sfunc = last_nonnull ); create function first( head anyarray, tail anyelement ) returns anyarray as $$ begin if head is null or head = '{}' then return ARRAY[tail]; end if; return head; end $$ language plpgsql; create function last( head anyarray, tail anyelement ) returns anyarray as $$ begin return ARRAY[tail]; end $$ language plpgsql; create function first( head anyarray ) returns anyelement as $$ begin return head[1]; end $$ language plpgsql; create aggregate first( anyelement ) ( stype = anyarray , initcond = '{}' , sfunc = first , finalfunc = first ); create aggregate last( anyelement ) ( stype = anyarray , initcond = '{}' , sfunc = last , finalfunc = first ); #### select first(v), first_nonnull(v), last(v), last_nonnull(v) from ( select NULL::text as v union all select 'one' as v union all select 'two' as v ) as q union all select first(v), first_nonnull(v), last(v), last_nonnull(v) from ( select 'one'::text as v union all select 'two' as v union all select NULL as v ) as q; #### first | first_nonnull | last | last_nonnull -------+---------------+------+-------------- | one | two | two one | one | | two (2 rows)