Как округлить среднюю до 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

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

Ответ 1

PostgreSQL не определяет round(double precision, integer). По причинам, которые @Mike Sherrill объясняет в комментариях "Cat Recall", версия раунда, которая требует точности, доступна только для 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 округляет цифры для вас как часть форматирования. Префикс FM сообщает to_char, что вам не нужно заполнение начальными пробелами.

Ответ 2

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

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

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

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

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


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

Вы можете overload использовать функцию ROUND с помощью

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

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

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

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

 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;

Try

 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 являются стандартными, см. руководство по встроенным математическим функциям.

Ответ 3

Попробуйте следующее:

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

Или просто:

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

Ответ 4

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

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

Ответ 5

Ошибка: функция round (double precision, integer) не существует

Решение: вам нужно добавить тип добавления, тогда он будет работать

Пример: round(extract(second from job_end_time_t)::integer,0)

Ответ 6

Вы можете использовать функцию ниже

 SELECT TRUNC(14.568,2);

результат покажет:

14.56

Вы также можете привести свою переменную к типу желания:

 SELECT TRUNC(YOUR_VAR::numeric,2)