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