drop function if exists _final_media_numeric(numeric[]) cascade;
CREATE OR REPLACE FUNCTION _final_media_numeric(numeric[])
   RETURNS numeric AS
$$
   SELECT AVG(val)
   FROM (
     SELECT val
     FROM unnest($1) val where val is not NULL
     ORDER BY 1
   ) sub;
$$
LANGUAGE 'sql' IMMUTABLE;


drop function if exists _final_mode_any(anyarray) cascade;
CREATE OR REPLACE FUNCTION _final_mode_any(anyarray)
  RETURNS anyelement AS
$BODY$
    SELECT a
    FROM unnest($1) a
    GROUP BY 1 
    ORDER BY COUNT(1) DESC, 1
    LIMIT 1;
$BODY$
LANGUAGE 'sql' IMMUTABLE;



drop aggregate if exists media(numeric);
CREATE AGGREGATE media(numeric)(
    sfunc = array_append,
    stype = numeric[],
    finalfunc = _final_media_numeric,
    initcond = '{}'

);


drop aggregate if exists media(anyarray);
CREATE AGGREGATE media(anyelement) (
  SFUNC=array_append, 
  STYPE=anyarray,
  FINALFUNC=_final_mode_any, 
  INITCOND='{}' 
);
