Multi-parameter aggregates. - Mailing list pgsql-general

From Berend Tober
Subject Multi-parameter aggregates.
Date
Msg-id 4381EFCA.2030708@seaworthysys.com
Whole thread Raw
Responses Re: Multi-parameter aggregates.  (Joe Conway <mail@joeconway.com>)
Re: Multi-parameter aggregates.  (Michael Fuhr <mike@fuhr.org>)
Re: Multi-parameter aggregates.  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-general
I'm interested in defining a covariance aggregate function. (As a
refresher, remember that covariance is a little bit like variance, but
is between two variables:

cov(X,Y)    =  <XY> - <X><Y>,

where the angular brackets in this case denote taking the averag.
Variance is a special case when X and Y are the same.)

But the whole user-defined aggregate thing is tough to get a handle on.
I'm not even sure if the direction I'm heading in below will actually
work, but as far as I got, I'm stuck on not knowing how to define a
aggregate that takes more that one variable as its argument, so its use
in SQL would look like, e.g.,

SELECT company, COVAR(year, sales) FROM annual_sales GROUP BY company;

Here is what I tried, and I'm wondering if the team here can help me
make this work (or tell me that the whole approach makes no sense,
etc.). All the DDL executes without syntactical errors until the last
function definition, and the problem is with the "  BASETYPE=numeric"
line, i.e., "ERROR:  AggregateCreate: function
covariance_accum(numeric[], numeric) does not exist"

CREATE TYPE public._covariance AS
    (n integer, x numeric, y numeric, xy numeric);


CREATE OR REPLACE FUNCTION public.covariance_accum(_covariance, numeric,
numeric)
    RETURNS _covariance AS '
    BEGIN
    _covariance.n := _covariance.n+1;
    _covariance.x := _covariance.x+$2;
    _covariance.y := _covariance.x+$3;
    _covariance.xy:= _covariance.xy+($1*$2);
    END;
    'LANGUAGE 'plpgsql' IMMUTABLE STRICT;
GRANT EXECUTE ON FUNCTION public.covariance_accum(_covariance, numeric,
numeric) TO public;
COMMENT ON FUNCTION public.covariance_accum(_covariance, numeric,
numeric) IS 'covariance aggregate transition function';


-- Need to include a check for N equal zero data points

CREATE OR REPLACE FUNCTION public.numeric_covariance(_covariance)
    RETURNS numeric AS '
    BEGIN
    (_covariance.xy/_covariance.n) -
(_covariance.x/_covariance.n)*(_covariance.y/_covariance.n);
    END;
    'LANGUAGE 'plpgsql' IMMUTABLE STRICT;
GRANT EXECUTE ON FUNCTION public.numeric_covariance(_covariance) TO public;
COMMENT ON FUNCTION public.numeric_covariance(_covariance) IS
'covariance aggregate final function';



CREATE AGGREGATE public.covariance(
  BASETYPE=numeric,
  SFUNC=covariance_accum,
  STYPE=numeric[],
  FINALFUNC=numeric_covariance,
  INITCOND='{0,0,0,0}'
);


/*
--I also tried this:

CREATE AGGREGATE covariance(
  BASETYPE='numeric, numeric',
  SFUNC=covariance_accum,
  STYPE=numeric[],
  FINALFUNC=numeric_covariance,
  INITCOND='{0,0,0,0}'
);

-- to no avail.
*/

Regards,
Berend



Attachment

pgsql-general by date:

Previous
From: Scott Marlowe
Date:
Subject: Re: Postgres Disconnection problems
Next
From: Bruno Wolff III
Date:
Subject: Re: SQL Help: Multiple LEFT OUTER JOINs