Как усечь значение двойной точности в PostgreSQL, сохранив ровно два первых десятичных знака? - PullRequest
0 голосов
/ 16 июня 2020

Я пытаюсь усечь значение двойной точности , когда я создаю json, используя функцию json_build_object() в PostgreSQL 11,8 , но безуспешно. Чтобы быть более точным, я пытаюсь усечь 19.9899999999999984 число ТОЛЬКО до двух десятичных знаков, но следя за тем, чтобы он НЕ округлял его до 20,00 (что он и делает), но чтобы сохранить его на 19,98 .

Кстати, до сих пор я пробовал использовать: 1) TRUNC(found_book.price::numeric, 2) и я получаю значение 20.00 2) ROUND(found_book.price::numeric, 2), и я получаю значение 19,99 -> пока что это ближайшее значение, но не то, что мне нужно 3) ROUND(found_book.price::double precision, 2), и я получаю

[42883] ОШИБКА: функция round (двойная точность, целое число) не существует

Также вот весь код Я используя:

create or replace function public.get_book_by_book_id8(b_id bigint) returns json as
$BODY$
declare
    found_book book;
    book_authors json;
    book_categories json;
    book_price double precision;
begin
    -- Load book data:
    select * into found_book
    from book b2
    where b2.book_id  = b_id;

    -- Get assigned authors
    select case when count(x) = 0 then '[]' else json_agg(x) end into book_authors
    from (select aut.*
        from book b
        inner join author_book as ab on b.book_id = ab.book_id
        inner join author as aut on ab.author_id = aut.author_id
        where b.book_id = b_id) x;

    -- Get assigned categories
    select case when count(y) = 0 then '[]' else json_agg(y) end into book_categories
    from (select cat.*
        from book b
        inner join category_book as cb on b.book_id = cb.book_id
        inner join category as cat on cb.category_id = cat.category_id
        where b.book_id = b_id) y;

    book_price = trunc(found_book.price, 2);
    -- Build the JSON response:
    return (select json_build_object(
        'book_id', found_book.book_id,
        'title', found_book.title,
        'price', book_price,
        'amount', found_book.amount,
        'is_deleted', found_book.is_deleted,
        'authors', book_authors,
        'categories', book_categories
    ));
end
$BODY$
language 'plpgsql';

select get_book_by_book_id8(186);

Как мне сохранить ТОЛЬКО две ПЕРВЫЕ десятичные цифры 19. 98 (приветствуются любые предложения / помощь)?

PS PostgreSQL версия 11,8

Ответы [ 2 ]

2 голосов
/ 16 июня 2020

In PostgreSQL 11,8 или 12,3 Я не могу воспроизвести:

# select trunc('19.9899999999999984'::numeric, 2);
 trunc 
-------
 19.98
(1 row)

# select trunc(19.9899999999999984::numeric, 2);
 trunc 
-------
 19.98
(1 row)

# select trunc(19.9899999999999984, 2);
 trunc 
-------
 19.98
(1 row)

На самом деле я могу воспроизвести с правильным типом и специальной настройкой:

# set extra_float_digits=0;
SET
# select trunc(19.9899999999999984::double precision::text::numeric, 2);
 trunc 
-------
 19.99
(1 row)

И возможное решение:

# show extra_float_digits;
 extra_float_digits 
--------------------
 3
(1 row)

select  trunc(19.9899999999999984::double precision::text::numeric, 2);
 trunc 
-------
 19.98
(1 row)

Но обратите внимание, что:

Примечание. Параметр extra_float_digits контролирует количество дополнительных значащих цифр, включаемых при плавающем значение точки преобразуется в текст для вывода. При значении по умолчанию 0 вывод будет одинаковым для всех платформ, поддерживаемых PostgreSQL. Его увеличение приведет к получению более точного представления сохраненного значения, но может быть непереносимым.

1 голос
/ 16 июня 2020

Как предложил @pifor, мне удалось это сделать, напрямую передав trunc(found_book.price::double precision::text::numeric, 2) в качестве значения в json_build_object следующим образом:

json_build_object(
        'book_id', found_book.book_id,
        'title', found_book.title,
        'price', trunc(found_book.price::double precision::text::numeric, 2),
        'amount', found_book.amount,
        'is_deleted', found_book.is_deleted,
        'authors', book_authors,
        'categories', book_categories
    )

Используя book_price = trunc(found_book.price::double precision::text::numeric, 2); и передав его как значение для 'price' не работает клавиша

Спасибо за вашу помощь. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...