web-dev-qa-db-fra.com

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

J'utilise PostgreSQL via le Ruby gem 'suite'.

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 je lance le code suivant:

SELECT ROUND(AVG(some_column))
FROM table

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

148
user1626730

PostgreSQL ne définit pas round(double precision, integer). Pour des raisons @ Mike Sherrill 'Cat Recall' explique 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 n'est qu'un alias abrégé pour double precision. Vous pouvez voir que PostgreSQL le développe dans la sortie).

Vous devez convertir la valeur à arrondir à numeric 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 formatez 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 d'obtenir un résultat text non affecté par la bizarrerie de votre la langue du 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 chiffres pour vous dans le cadre du formatage. Le préfixe FM indique à to_char que vous ne souhaitez pas de remplissage avec des espaces.

209
Craig Ringer

Essayez aussi l'ancienne syntaxe de casting,

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

fonctionne avec n’importe quelle version de PostgreSQL.

Il y a un manque de surcharge dans certaines fonctions PostgreSQL, pourquoi (???): Je pense que "c'est un manque" (!), Mais @ CraigRinger, @Catcall et l'équipe de PostgreSQL s'accordent sur "la logique historique de pg".

PS: un autre point concernant l’arrondissement est la précision , cochez la case réponse de @ IanKenney .


Surcharge comme stratégie de casting

Vous pouvez surcharge la fonction ROUND 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 retourne un type NUMERIC ... Pour conserver la première surcharge d'utilisation courante, 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;

Essayer

 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 des surcharges, montrera quelque chose comme,

 Schéma | Nom | Type de données de résultat | Types de données d'argument 
 ------------ + ------- + ------------------ + - -------------------------- 
 myschema | tour | double précision | double precision, text, int 
 myschema | tour | numérique | double precision, int 
 pg_catalog | tour | double précision | double précision 
 pg_catalog | tour | numérique | numérique 
 pg_catalog | tour | numérique | numérique, int 

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

68
Peter Krauss

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
29
atiruz

Selon la réponse de Bryan , vous pouvez le faire pour limiter les décimales dans une requête. Je convertis de km/h en m/s et l’affiche sous forme de dygraphes, mais lorsque je l’ai fait sous forme de dygraphes, c’était étrange. Ça a l'air bien quand on fait le calcul dans la requête. Ceci est sur postgresql 9.5.1.

select date,(wind_speed/3.6)::numeric(7,1) from readings;
2
kometen

Erreur: la fonction round (double precision, integer) n'existe pas

Solution: Vous devez ajouter un casting puis ça fonctionnera

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

1
user5702982

vous pouvez utiliser la fonction ci-dessous

 SELECT TRUNC(14.568,2);

le résultat montrera:

14.56

vous pouvez aussi transtyper votre variable selon le type de désir:

 SELECT TRUNC(YOUR_VAR::numeric,2)
0
info vif