Как округлить среднее значение до 2 десятичных знаков в PostgreSQL?

Я использую PostgreSQL через продолжение Ruby gem.

Я пытаюсь округлить до двух знаков после запятой.

вот мой код:

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

Я получаю следующую ошибку:

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

Я не получаю ошибок при запуске следующего кода:

SELECT ROUND(AVG(some_column))
FROM table

кто-нибудь знает, что я делаю неправильно?

5 ответов


PostgreSQL не определяет round(double precision, integer). По причинам @Catcall объясняет в комментариях, версия раунда, которая принимает точность, доступна только для 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)

(в приведенном выше, обратите внимание, что float8 это просто сокращенный псевдоним для double precision. Вы можете видеть, что PostgreSQL расширяет его в выходных данных).

вы должны привести значение, которое будет округлено до numeric использовать форму двух аргументов round. Просто добавьте ::numeric для стенографии, как round(val::numeric,2).


если вы форматируете для отображения пользователю, не используйте round. Использовать to_char (см.: функции форматирования данных типа в руководстве), который позволяет задать формат и дает вам text результат, который не зависит от того, что ваш клиентский язык может сделать с numeric значения. Например:

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

to_char будет округлять номера для вас как часть форматирования. The FM префикс сообщает to_char что вы не хочу дополняя пробелы.


попробуйте также старый синтаксис для литья,

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

работает с любой версией PostgreSQL.

отсутствуют перегрузки в некоторых функциях PostgreSQL почему (???): Я думаю, "это недостаток" (!), но @CraigRinger, @Catcall и команда PostgreSQL согласны с "историческим обоснованием pg".

PS: еще один момент о округлении -точность, Регистрация @IanKenney по ответ.


перегрузка как стратегия литья

вы можете перегрузка круглая функция с,

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

теперь ваша инструкция будет работать нормально, попробуйте (после создания) функция

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

но он возвращает числовой тип... Чтобы сохранить первую перегрузку commom-usage, мы можем вернуть тип FLOAT, когда предлагается текстовый параметр,

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

попробовать

 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: проверка \df round после перегрузки, покажет что-то вроде

 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          

на pg_catalog функции являются функциями по умолчанию, см. руководство по встроенным математическим функциям.


попробуйте с помощью этого:

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

или просто:

SELECT round (2/3::DECIMAL, 2)::TEXT
-- RESULT: 0.67

ошибка: функция round (двойная точность, целое число) не существует

решение: вам нужно addtype cast, тогда он будет работать

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


по данным Брайан ответ вы можете сделать это, чтобы ограничить десятичных знаков в запросе. Я конвертирую из km/h в m / s и отображаю его в диграфах, но когда я делал это в диграфах, это выглядело странно. Выглядит отлично при выполнении вычисления в запросе вместо этого. Это на postgresql 9.5.1.

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