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

I am in the middle of migrating some queries which have been running for ages with MySQL database which is now in Postgres having the same structure. I got stuck with a simple round function which ends with the following error message.

ERROR: function round(double precision, integer) does not exist

part of the select which does not work:

round(floor(pools.available_capacity_in_kb/1024/1024/1024*100)/100,2) as free,

pools.available_capacity_in_kb is stored as BIGINT in the database (Postgres 10.9)

funnydman's user avatar

funnydman

8,6034 gold badges36 silver badges52 bronze badges

asked Nov 6, 2019 at 14:03

radek lopatecki's user avatar

radek lopateckiradek lopatecki

6031 gold badge5 silver badges5 bronze badges

0

I had the same problem with geograpic coordinates. The longitude was in double precision from the open street map data and needed a rouded value.

My solution work fine:

select ROUND(CAST(longitude AS numeric),2) from my_points; 

answered Mar 25, 2021 at 13:11

Gerd's user avatar

1

Besides the type CAST syntax, you can use the following syntax to convert a value of one type into another (cast :: operator):

select ROUND(value::numeric, 2) from table_x; 

Notice that the cast syntax with the cast operator (::) is PostgreSQL-specific and does not conform to the SQL standard.

Alejandro Veltri's user avatar

answered Aug 8, 2021 at 11:15

funnydman's user avatar

funnydmanfunnydman

8,6034 gold badges36 silver badges52 bronze badges

1

The core of the problem is somewhere else. PostgreSQL uses long division for integer and bigint numbers (when on both parts of division are int, bigint values). So result of pools.available_capacity_in_kb/1024/1024/1024*100)/100 is bigint. Probably this is not, what you expect.

postgres=# df round
                          List of functions
+------------+-------+------------------+---------------------+------+
|   Schema   | Name  | Result data type | Argument data types | Type |
+------------+-------+------------------+---------------------+------+
| pg_catalog | round | double precision | double precision    | func |
| pg_catalog | round | numeric          | numeric             | func |
| pg_catalog | round | numeric          | numeric, integer    | func |
+------------+-------+------------------+---------------------+------+
(3 rows)

There is not any round function for bigint (because it has not any sense).
Please try to fix it by using float division like

pools.available_capacity_in_kb/1024/1024/1024*100)/100.0

Now, the result will be numeric, and the function round(numeric, int) exists — so it should works.

Dave Yu's user avatar

Dave Yu

3064 silver badges15 bronze badges

answered Nov 6, 2019 at 14:18

Pavel Stehule's user avatar

Pavel StehulePavel Stehule

41.8k5 gold badges90 silver badges93 bronze badges

5

you can use following syntax as well

select round((value::Decimal),2) from table_name;

Notice that the cast syntax with the cast operator (::) is PostgreSQL-specific and does not conform to the SQL standard.

answered Sep 24, 2022 at 16:31

j k's user avatar

j kj k

311 silver badge6 bronze badges

написал запрос

select
              'request_median_duration' as metric_name,
              EXTRACT(EPOCH FROM request_median_duration)/60 as metric_value,
              TO_CHAR(NOW(), 'YYYY-MM-DD HH:MM:SS') as push_dttm
              from mp_statistics

нужно округлить до 2 знака до запятой
попробовал сделать так

select
              'request_median_duration' as metric_name,
              ROUND(EXTRACT(EPOCH FROM request_median_duration)/60,2) as metric_value,
              TO_CHAR(NOW(), 'YYYY-MM-DD HH:MM:SS') as push_dttm
              from mp_statistics

возвращается ошибка

SQL Error [42883]: ERROR: function round(double precision, integer) does not exist
  Подсказка: No function matches the given name and argument types. You might need to add explicit type casts.
  Позиция: 94

выкрутился так

select
              'request_median_duration' as metric_name,
              ROUND(EXTRACT(EPOCH FROM request_median_duration)/60*100)/100 as metric_value,
              TO_CHAR(NOW(), 'YYYY-MM-DD HH:MM:SS') as push_dttm
              from mp_statistics

какой есть еще более изящный вариант?

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

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

Solution 1

The core of the problem is somewhere else. PostgreSQL uses long division for integer and bigint numbers (when on both parts of division are int, bigint values). So result of pools.available_capacity_in_kb/1024/1024/1024*100)/100 is bigint. Probably this is not, what you expect.

postgres=# df round
                          List of functions
+------------+-------+------------------+---------------------+------+
|   Schema   | Name  | Result data type | Argument data types | Type |
+------------+-------+------------------+---------------------+------+
| pg_catalog | round | double precision | double precision    | func |
| pg_catalog | round | numeric          | numeric             | func |
| pg_catalog | round | numeric          | numeric, integer    | func |
+------------+-------+------------------+---------------------+------+
(3 rows)

There is not any round function for bigint (because it has not any sense).
Please try to fix it by using float division like

pools.available_capacity_in_kb/1024/1024/1024*100)/100.0

Now, the result will be numeric, and the function round(numeric, int) exists — so it should works.

Solution 2

I had the same problem with geograpic coordinates. The longitude was in double precision from the open street map data and needed a rouded value.

My solution work fine:

select ROUND(CAST(longitude AS numeric),2) from my_points; 

Solution 3

Besides the type CAST syntax, you can use the following syntax to convert a value of one type into another (cast :: operator):

select ROUND(value::numeric, 2) from table_x; 

Notice that the cast syntax with the cast operator (::) is PostgreSQL-specific and does not conform to the SQL standard.

Comments

  • I am in the middle of migration some queries which have been running for ages with MySQL database which is now in Postgres having the same structure. I got stuck with simple round function which ends with the following error message.

    ERROR: function round(double precision, integer) does not exist

    part of the select which does not work:

    round(floor(pools.available_capacity_in_kb/1024/1024/1024*100)/100,2) as free,
    

    pools.available_capacity_in_kb is stored as BIGINT in the database (Postgres 10.9)

  • The function sequence «round(floor( …» is not necessary, and does not make since anyway. The floor function returns «the largest integer less that or equal to the argument», You cannot round an integer — at least not without an UDF.

  • Thanks a lot for a quick turnaround Pavel. You are right — round function is not working on bigint. I changed data type to numeric and that worked well. round(floor(pools.available_capacity_in_kb::numeric/1024/102‌​4/1024*100)/100,2) as free,

  • @radeklopatecki so please, close this task

  • The solution worked for me when I ran into the issue while using Postgres 9.6 in db-fiddle

Recents

Related

With current master, the postgresql tests fail with this error (among others):

====================================================================
PostGIS(1): Query: DECLARE qgis_1166 BINARY CURSOR FOR SELECT "key1"::text,"key2"::text,"pk"::text,"cnt"::text,"name"::text,"name2"::text,"num_char"::text FROM "qgis_test"."someDataCompound" WHERE (round(("cnt" / ((66.67)::real)),0) <= 2) returned 7 [ERROR:  function round(double precision, integer) does not exist                                        ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
]
PostGIS(1): 1 cursor states lost.
SQL: DECLARE qgis_1166 BINARY CURSOR FOR SELECT "key1"::text,"key2"::text,"pk"::text,"cnt"::text,"name"::text,"name2"::text,"num_char"::text FROM "qgis_test"."someDataCompound" WHERE (round(("cnt" / ((66.67)::real)),0) <= 2)
LINE 1: ...::text FROM "qgis_test"."someDataCompound" WHERE (round(("cn...
                                                    ==
FAIL: testStyleDatabaseWithService (__main__.TestPyQgsPostgresProvider)
Test saving style in DB using a service file.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/src/qgis/qgis-master/tests/src/python/test_provider_postgres.py", line 1318, in testStyleDatabaseWithService
    self.assertEqual(len(ids), 1)
AssertionError: 0 != 1

I’m running it against PostgreSQL-9.6.9
Indeed round(float8, int) does not exist, while round(numeric, int) does:

strk=# select round(1.01::float8, 2);
ERROR:  function round(double precision, integer) does not exist
LINE 1: select round(1.01::float8, 2);
               ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
strk=# select round(1.01::numeric, 2);
 round
-------
  1.01
(1 row)

strk=# select version();
                                             version                                              
--------------------------------------------------------------------------------------------------
 PostgreSQL 9.6.9 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.2.0-8ubuntu3.2) 7.2.0, 64-bit
(1 row)

Понравилась статья? Поделить с друзьями:
  • Ошибки газового котла бакси экофор
  • Ошибка фри кам
  • Ошибки выборочного наблюдения реферат
  • Ошибка формата электронной почты
  • Ошибка формата файла обмена универсальный обмен данными