функция round(numeric,integer) в PostgreSQL округляет только в большую сторону:
round(cast (41.0255 as numeric),3) ==> 41.026
Так как нам нужна круглая функция, которая возвращает 41.025 и (что удивительно) такой функции нет в PostgreSQL (мы используем 9.1.5), мы написали функцию-обертку, которая в самой первой версии довольно наивна и грубо... но мы не нашли ничего лучше из-за отсутствия встроенной поддержки такого рода проблем в plpgsql.
Код показан ниже. Проблема в том, что он слишком медленный для наших целей. Не могли бы вы предложить лучший способ справиться с этой задачей?
Вот код:
CREATE OR REPLACE FUNCTION round_half_down(numeric,integer) RETURNS numeric
AS $$
DECLARE
arg ALIAS FOR $1;
rnd ALIAS FOR $2;
tmp1 numeric;
res numeric;
BEGIN
tmp1:=arg;
IF cast(tmp1 as varchar) ~ '5$' THEN res:=trunc(arg,rnd);
ELSE res:=round(arg,rnd);
END IF;
RETURN res;
END;
$$ LANGUAGE plpgsql;
Мне нужно привести числовое значение и использовать регулярное выражение... это то, что (я полагаю) убивает производительность.
Просто чтобы вы знали: нам это нужно, потому что мы должны сравнивать числа, которые были сохранены в двух разных столбцах (в двух разных таблицах), но с разными числовыми типами данных: одно двойное, а другое действительное. Проблема в том, что при вставке в столбец с реальным типом данных PostgreSQL выполняет ROUND HALF DOWN, в то время как он не предоставляет такой возможности через свои математические функции!
РЕДАКТИРОВАТЬ:
Функция на самом деле прослушивается. Это была первая быстрая переработка как попытка улучшить производительность работающей функции, но очень медленная.
Поведение должно соответствовать следующему:IF
десятичная цифра, которая не учитывается при округлении, равна <=5 => trunc
ELSE
округлению в большую сторону.
Несколько примеров:
select round_half_down(cast (41.002555 as numeric),3) -- 41.002
select round_half_down(cast (41.002555 as numeric),4) -- 41.0025
select round_half_down(cast (41.002555 as numeric),5) -- 41.00255
в то время как функция раунда в PostgreSQL дает:
select round(cast (41.002555 as numeric),3) -- 41.003
-41.0255
до-41.025
или-41.026
? Также: вы хотите, чтобы41.02551
округлялось до41.025
или41.026
? - person Erwin Brandstetter   schedule 21.09.2012