Re: avg() for timestamp

From: Bruno Wolff III <bruno(at)wolff(dot)to>
To: Neil Conway <neilc(at)samurai(dot)com>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: avg() for timestamp
Date: 2004-03-08 07:44:00
Message-ID: 20040308074400.GA20537@wolff.to
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Sat, Mar 06, 2004 at 21:50:52 -0500,
Neil Conway <neilc(at)samurai(dot)com> wrote:
> It seems to me the following should Just Work:
>
> nconway=# create table t1 (a timestamp);
> CREATE TABLE
> nconway=# insert into t1 values (now());
> INSERT 17164 1
> nconway=# insert into t1 values (now());
> INSERT 17165 1
> nconway=# insert into t1 values (now());
> INSERT 17166 1
> nconway=# insert into t1 values (now());
> INSERT 17167 1
> nconway=# select avg(a) from t1;
> ERROR: function avg(timestamp without time zone) does not exist
> HINT: No function matches the given name and argument types. You may
> need to add explicit type casts.
>
> It seems we could add the necessary aggregate function to do this.
> Seems worth doing to me.
>
> Any comments?

While there is a way to calculate an average timestamp, I don't think
there is an easy way to do this automatically with say a polymorphic
aggregate. You need to know that there is a related type interval that
can be used to keep track of differences in timestamps and that can be
added back to a timestamp at the end.

While this may or may not be suitable for direct use, it will work
for timestamps. A similar thing could be done for timestampz.
I tried the following out with no rows, a single row, several rows,
and some null rows and it seemed to work.

drop aggregate avg(timestamp);
drop function timestamp_sfunc(timestamp_avg, timestamp);
drop function timestamp_ffunc(timestamp_avg);
drop type timestamp_avg;

create type timestamp_avg as (first timestamp, total interval, num float8);

create function timestamp_sfunc(timestamp_avg, timestamp)
returns timestamp_avg
immutable language 'sql' as '
select
case when $2 is null then
$1.first
else
case when $1.first is null then
$2
else
$1.first
end
end,
case when $2 is null then
$1.total
else
case when $1.first is null then
''0''::interval
else
$1.total + ($2 - $1.first)
end
end,
case when $2 is null then
$1.num
else
case when $1.first is null then
''1''::float8
else
$1.num + ''1''::float8
end
end
';

create function timestamp_ffunc(timestamp_avg)
returns timestamp
immutable language 'sql'
as 'select $1.first + ($1.total / $1.num)'
;

create aggregate avg (
basetype = timestamp,
sfunc = timestamp_sfunc,
stype = timestamp_avg,
finalfunc = timestamp_ffunc
);

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Claudio Natoli 2004-03-08 10:12:52 socket calls in signal handler (WAS: APC + socket restrictions un der Win32?)
Previous Message Marc G. Fournier 2004-03-08 05:53:03 Re: 7.4.2 packaged ...