加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

postgresql圆半下来功能

发布时间:2020-12-13 15:57:31 所属栏目:百科 来源:网络整理
导读:PostgreSQL中的round(数字,整数)函数只会向上舍入: round(cast (41.0255 as numeric),3) == 41.026 由于我们需要一个返回41.025的圆函数(非常令人惊讶)在PostgreSQL中没有这样的函数(我们使用的是9.1.5),我们编写了一个“包装”函数,在第一个版本中它非常天
PostgreSQL中的round(数字,整数)函数只会向上舍入:

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;

我需要转换数值并使用正则表达式…这就是(我猜)杀死表演的东西.

您知道:我们需要这个,因为我们必须比较存储在两个不同列(在两个不同的表上)但具有不同数值数据类型的数字:一个是double,一个是real.问题是当插入真实数据类型列时,PostgreSQL执行ROUND HALF DOWN,而它不通过其数学函数提供这样的选项!

编辑:
该功能实际上是错误的.是第一次快速重写,试图提高工作功能的性能,但速度很慢.

行为必须符合以下条件:
如果从舍入中推出的十进制数是< = 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中的round函数给出:

select round(cast (41.002555 as numeric),3) -- 41.003

解决方法

We have to compare numbers that were stored in two different columns
(on two different tables) but with different numeric data type: one is
double and one is real.

这应该非常快速和简单:

SELECT dp_col,real_col
FROM   tbl
WHERE  dp_col::real = real_col

基本上,只需将双精度数转换为实数即可进行比较.

如果这对你不起作用,这个SQL函数应该做一个合适的工作并且工作得更快:

CREATE OR REPLACE FUNCTION round_half_down1(numeric,int)
  RETURNS numeric LANGUAGE sql AS
$func$
SELECT CASE WHEN abs($1%0.1^$2) < .6 * 0.1^$2 THEN
         trunc($1,$2)
    ELSE round($1,$2) END;
$func$

现在修复了负数,并在评论中输入@sufleR.
您也可以使用包含的CASE表达式.

% .. modulo operator
^ .. exponentiation

这是一个可用于基准测试的快速测试:

SELECT n                                   -- Total runtime: 36.524 ms,round_half_down1(n,3)               -- Total runtime: 70.493 ms,round_down_to_decimal_places(n,3)   -- Total runtime: 74.690 ms,round_half_down(n,3)                -- Total runtime: 82.191 ms
FROM  (SELECT random()::numeric AS n FROM generate_series(1,10000)) x
WHERE  round_down_to_decimal_places(n,3)
    <> round_half_down1(n,3)

它还演示了@ Parveen的函数和编辑后的版本是如何计算错误的 – 它们不应该在哪里截断().

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读