Як округлити в середньому до 2 знаків після коми в PostgreSQL?


192

Я використовую PostgreSQL через "продовження" дорогоцінного каміння Ruby.

Я намагаюся округлити до двох знаків після коми.

Ось мій код:

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

Хтось знає, що я роблю неправильно?


3
Ваше повідомлення про помилку не відповідає коду у вашому запитанні.
mu занадто короткий

Синтаксична помилка в стороні, це тісно пов'язане питання на dba.SE проливає трохи світла на округлення подвійних точних чисел у PostgreSQL.
Ервін Брандстеттер

@muistooshort, Дякую за вказівку на це Слід сказати "круглий", де написано "сер". Відредаговано.
користувач1626730

для пошуку результатів, я також отримую цей підказку як вихід з підказки:HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Vzzarr

Відповіді:


266

PostgreSQL не визначає round(double precision, integer). З причин @Mike Sherrill 'Cat 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що ви не хочете відступів з провідними пробілами.


Хм. Коли я пробую ROUND(CAST(FLOAT8 '3.1415927' AS NUMERIC),2);, я отримую '0,314E1'. І у мене написаний код, ROUND(AVG(val),2)поки я все ще отримую помилку, яку я описав у своєму запитанні.
користувач1626730

Я просто бігав ROUND(CAST(FLOAT8 '3.1415927' AS NUMERIC),2);на PgAdmin та Ruby. З PgAdmin я отримую 3,14, але з Ruby (використовуючи він Sequel gem) я отримую '0,314E1'. Цікаво, чому це ...
користувач1626730

12
"Чомусь версія круглої форми, яка має точність, доступна лише для числових." Числа з плаваючою комою є "корисними наближеннями". Якщо ви попросите код округлити число з плаваючою комою до двох десяткових знаків і повернути ще одне число з плаваючою комою, немає гарантії, що найближче наближення до відповіді "правильний" матиме лише дві цифри праворуч від десяткової. Числівники ефективно масштабують цілі числа; у них немає такої проблеми.
Майк Шеррілл 'Відкликання котів'

@Catcall Добре - doubleверсія версії roundпотрібно повернути numericабо (ugh) text, тому вона може також взяти numericаргумент.
Крейг Рінгер

6
Для тих, хто намагається знайти коментар від @Catcall: зараз це Майк Шеррілл 'Cat Recall'
18446744073709551615

89

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

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

працює з будь-якою версією PostgreSQL.

У деяких функціях PostgreSQL не вистачає перевантажень , чому (???): я думаю, що "це недолік" (!), Але @CraigRinger, @Catcall та команда PostgreSQL погоджуються щодо "історичного обгрунтування pg".

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


Перевантаження як стратегія кастингу

Ви можете перевантажити функцію 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

але він повертає числовий тип ... Щоб зберегти перше перевантаження з використанням комутатора, ми можемо повернути тип 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;

Спробуйте

 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після перевантажень покаже щось на зразок,

Схема | Назва | Тип даних про результати | Типи даних аргументів
------------ + ------- + ------------------ + ---------- ------------------
 мішема | круглі | подвійна точність | подвійна точність, текст, int
 мішема | круглі | числовий | подвійна точність, int
 pg_catalog | круглі | подвійна точність | подвійна точність            
 pg_catalog | круглі | числовий | числовий   
 pg_catalog | круглі | числовий | числовий, інт          

Ці pg_catalogфункції є ті , за замовчуванням, см керівництво по збірці-математичних функцій .


38

Спробуйте з цим:

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

Або просто:

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

5
Я вважаю це набагато більш стислим і прямим кроком вперед із щоденною відповіддю на це питання. : лук:
craastad

2
Те ж саме! Дуже коротке і корисне рішення.
Олексій Шабрамов

7

ви можете використовувати функцію нижче

 SELECT TRUNC(14.568,2);

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

14.56

Ви також можете привести свою змінну до типу бажання:

 SELECT TRUNC(YOUR_VAR::numeric,2)

3

Відповідно до відповіді Брайана, ви можете це зробити для обмеження десяткових знаків у запиті. Я перетворюю з км / год в м / с і відображаю його в малюнках, але коли я робив це на диграфах, це виглядало дивно. Виглядає нормально, роблячи замість цього розрахунок у запиті. Це на postgresql 9.5.1.

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


1

Помилка: функція кругла (подвійна точність, ціле число) не існує

Рішення : Вам потрібно додати тип типу, тоді він спрацює

Наприклад: round(extract(second from job_end_time_t)::integer,0)


0

виберіть ROUND (SUM (сума) :: числовий, 2) як total_amount FROM операцій

дає: 200234.08

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.