Comment arrondir une moyenne à 2 décimales dans PostgreSQL?

J'utilise PostgreSQL via la gem Ruby 'sequel'.

J'essaie d'arrondir à deux décimales.

Voici mon code:

SELECT ROUND(AVG(some_column),2)    
FROM table

Je reçois l'erreur suivante:

PG::Error: ERROR:  function round(double precision, integer) does 
not exist (Sequel::DatabaseError)

Je ne reçois aucune erreur lorsque j'exécute le code suivant:

SELECT ROUND(AVG(some_column))
FROM table

Est-ce que quelqu'un sait ce que je fais mal?

104
demandé sur Nikolay Fominyh 2012-10-29 01:15:11

5 réponses

PostgreSQL ne définit pas round(double precision, integer). Pour des raisons expliquées par @Catcall dans les commentaires, la version de round qui prend une précision n'est disponible que pour numeric.

regress=> SELECT round( float8 '3.1415927', 2 );
ERROR:  function round(double precision, integer) does not exist

regress=> \df *round*
                           List of functions
   Schema   |  Name  | Result data type | Argument data types |  Type  
------------+--------+------------------+---------------------+--------
 pg_catalog | dround | double precision | double precision    | normal
 pg_catalog | round  | double precision | double precision    | normal
 pg_catalog | round  | numeric          | numeric             | normal
 pg_catalog | round  | numeric          | numeric, integer    | normal
(4 rows)

regress=> SELECT round( CAST(float8 '3.1415927' as numeric), 2);
 round 
-------
  3.14
(1 row)

(dans ce qui précède, notez que float8 est juste un alias raccourci pour double precision. Vous pouvez voir que PostgreSQL l'étend dans la sortie).

Vous devez convertir la valeur à arrondir à {[3] } pour utiliser la forme à deux arguments de round. Il suffit d'ajouter ::numeric pour la distribution abrégée, comme round(val::numeric,2).


Si vous êtes formatage pour l'affichage à l'utilisateur, n'utilisez pas round. Utilisez to_char (Voir: fonctions de formatage de type de données dans le manuel), ce qui vous permet de spécifier un format et vous donne un résultat text qui n'est pas affecté par la bizarrerie que votre langage client peut faire avec les valeurs numeric. Par exemple:

regress=> SELECT to_char(float8 '3.1415927', 'FM999999999.00');
    to_char    
---------------
 3.14
(1 row)

to_char arrondira les numéros pour vous dans le cadre du formatage. Le préfixe FM indique à to_char que vous ne voulez pas de remplissage avec des espaces de début.

153
répondu Craig Ringer 2012-10-29 23:39:18

Essayez aussi l'ancienne syntaxe pour la coulée,

SELECT ROUND(AVG(some_column)::numeric,2)    
FROM table;

Fonctionne avec N'importe quelle version de PostgreSQL.

Il y a un manque de surcharges dans certaines fonctions PostgreSQL, pourquoi???): Je pense que "c'est un manque" (!), mais @CraigRinger, @ Catcall et L'équipe PostgreSQL sont d'accord sur "la logique historique de pg".

PS: un autre point sur l'arrondi est précision , vérifiez la réponse de @IanKenney.


Surcharge comme stratégie de coulée

Vous pouvez surcharge la fonction ronde avec,

 CREATE FUNCTION ROUND(float,int) RETURNS NUMERIC AS $$
    SELECT ROUND($1::numeric,$2);
 $$ language SQL IMMUTABLE;

Maintenant, votre instruction fonctionnera bien, essayez (après la création de la fonction)

 SELECT round(1/3.,4); -- 0.3333 numeric

Mais il renvoie un type numérique... Pour préserver la première surcharge d'utilisation commom, nous pouvons renvoyer un type FLOAT lorsqu'un paramètre TEXT est proposé,

 CREATE FUNCTION ROUND(float, text, int DEFAULT 0) 
 RETURNS FLOAT AS $$
    SELECT CASE WHEN $2='dec'
                THEN ROUND($1::numeric,$3)::float
                -- ... WHEN $2='hex' THEN ... WHEN $2='bin' THEN... complete!
                ELSE 'NaN'::float  -- like an error message 
            END;
 $$ language SQL IMMUTABLE;

Essayez

 SELECT round(1/3.,'dec',4);   -- 0.3333 float!
 SELECT round(2.8+1/3.,'dec',1); -- 3.1 float!
 SELECT round(2.8+1/3.,'dec'::text); -- need to cast string? pg bug 

PS: vérifier \df round après les surcharges, montrera quelque chose comme,

 Schema     |  Name | Result data type | Argument data types 
------------+-------+------------------+----------------------------
 myschema   | round | double precision | double precision, text, int
 myschema   | round | numeric          | double precision, int
 pg_catalog | round | double precision | double precision            
 pg_catalog | round | numeric          | numeric   
 pg_catalog | round | numeric          | numeric, int          

Les fonctions pg_catalog sont celles par défaut, voir manuel de mathématiques intégrées fonctions .

52
répondu Peter Krauss 2017-05-23 12:34:36

Essayez avec ceci:

SELECT to_char (2/3::float, 'FM999999990.00');
-- RESULT: 0.67

Ou simplement:

SELECT round (2/3::DECIMAL, 2)::TEXT
-- RESULT: 0.67
15
répondu atiruz 2016-05-25 21:33:29

Erreur: la fonction ronde (double précision, entier) n'existe pas

Solution: Vous devez addtype cast ensuite, il sera

Ex: round(extract(second from job_end_time_t)::integer,0)

2
répondu user5702982 2015-12-21 11:32:06