2014-05-11 6 views
2

J'ai une table postgresql avec plusieurs champs contenant des entiers (a1, a2, a3 etc.).Fonctions d'agrégation sur plusieurs colonnes dans postgres

Je souhaite exécuter des fonctions agrégées (moyenne, écart-type, etc.) sur plusieurs colonnes à la fois. (Certains d'entre eux peuvent avoir un nombre raisonnable de valeurs nulles, donc je ne veux pas simplement générer des moyennes de colonnes et ensuite les calculer en moyenne).

je peux obtenir un ensemble d'entiers avec

SELECT unnest(array[a1,a2,a3]) as values FROM table 

mais je ne peux donc pas obtenir les fonctions d'agrégation pour prendre cela comme entrée.

Quelqu'un peut-il me donner des indices sur la façon dont cela pourrait fonctionner?

Répondre

2

Avec un sous-requête que vous avez toutes les lignes à votre disposition:

SELECT sum(val) FROM (
    SELECT unnest(array[a1,a2,a3]) as val FROM table) alias; 

Vous pouvez également regrouper vos lignes, par exemple:

SELECT field, sum(val) FROM (
    SELECT field, unnest(array[a1,a2,a3]) as val FROM table) alias 
GROUP BY field; 
+0

Spot sur - Il me manquait le _alias_ - ce serait pourquoi je continuais à obtenir l'erreur de syntaxe ... – sparky

1

vous pouvez définir des agrégats propres pour la variable de tableau:

CREATE OR REPLACE FUNCTION public.sum_sfunc(double precision, double precision[]) 
RETURNS double precision LANGUAGE sql 
AS $function$ 
    SELECT coalesce($1,0) + sum(v) FROM unnest($2) g(v) 
$function$ 

CREATE AGGREGATE sum(BASETYPE=double precision[], 
         SFUNC=sum_sfunc, STYPE=double precision); 

postgres=# select * from fo; 
a │ b 
────┼──── 
10 │ 20 
30 │ 40 
(2 rows) 

postgres=# select sum(array[a,b]) from fo; 
sum 
───── 
100 
(1 row) 

étapes similaires que vous pouvez faire avec d'autres agrégats, mais la mise en œuvre d'AVG est peu plus difficile, et la médiane est au niveau suivant. Mais tout est possible, voir http://www.postgresql.org/docs/9.3/static/xaggr.html

+1

Hmm. Merci pour votre aide, mais je ne suis pas sûr que j'ai envie de réimplémenter toutes les fonctions agrégées! Il semble juste un peu étrange que je ne puisse pas passer le setof qui vient de ma requête originale à ceux qui existent déjà. – sparky

Questions connexes