根据最小数字

时间:2015-10-27 21:26:16

标签: sql postgresql math postgresql-9.3

假设我的2值为NUMERIC。我想将0.0001添加到此2以获取2.0001。如果我已2.01,我想向其添加0.000001以获取2.010001

基本上,我想添加一个比数字最后一位(最高精度数字)小4个数量的数字。

对于2.000的奇怪情况,我可以获得2.00012.0000001

我查看了

我考虑过是否有某种方法可以使用PostgreSQL数据类型函数来提取这些信息,但我找不到任何方法。

我也试着考虑一些计算它的数学方法。我考虑了log,但这会向我提供有关最高数量级数字的信息,而不是最低数字。

背景

这是信息性的。我只是提供,因为如果我看到其他人提出这个问题,我的第一个想法是,"他们想要做什么?"

我完全清楚这是一个非常奇怪的用例。我面临的问题是,由于一些奇怪的精确问题,我经常通过PostGIS从GEOS收到TopologyException。 (这与我的输入数据不是特别干净有关。不幸的是,我处理大量数据并且"检测并手动修复问题几何图形"不是一种选择。)值I处理有效的是容差参数。它被送入缓冲区和捕捉函数。奇怪的是,通过这么小的量来改变它通常足以超越错误并获得我需要的结果。为了避免这些错误,我打算在我的一些操作中构建一种带有稍微改变值的重试机制。所以我试图弄清楚如何计算这个稍微改变的值。

2 个答案:

答案 0 :(得分:1)

使用简单的操作:

SELECT col
 , col + POW(0.1,(LENGTH(regexp_replace(CAST(col % 1 AS VARCHAR), '[0]+$', ''))-2))*0.0001 AS result
FROM tab;

SqlFiddleDemo

  1. col % 1 - 获取分数部分
  2. CAST到字符串
  3. REGEX_REPLACE - 删除尾随0
  4. LENGTH - 获取字符串的长度 - 20.部分)
  5. POW(0.1, ...) - 获取乘数
  6. 乘以0.0001
  7. 添加到初始值
  8. 编辑:

    更简单: 号码 - >文字 - >删除尾随0 - >追加0001 - >编号

    SELECT col,
     CAST(regexp_replace(CAST(col * 1.0 AS VARCHAR), '[0]+$', '') || '0001' AS NUMERIC(30,20)) AS result
    FROM tab;
    

    SqlFiddleDemo

    输出:

    ╔═════════════╦════════════════╗
    ║     col     ║     result     ║
    ╠═════════════╬════════════════╣
    ║ 2           ║ 2.0001         ║
    ║ 2.01        ║ 2.010001       ║
    ║ 2.05000103  ║ 2.050001030001 ║
    ╚═════════════╩════════════════╝
    

答案 1 :(得分:1)

我想在没有pow()的情况下这样做。 函数中的查询仅使用文本操作和强制转换。 它捕获一个整数的特殊情况。

create or replace function add_4_pos_digits (val numeric)
returns numeric language sql as $$
    select val+ ('.' || repeat('0', d) || '1')::numeric
    from (
        select case d when 0 then 3 else d+ 2 end d
        from (
            select strpos(reverse(rtrim(val::text, '0')), '.') d
            ) q
        ) q;
$$;

create table example (val numeric);
insert into example values (1), (1.1), (1.01), (1.00001);

select val, add_4_pos_digits(val)
from example;

   val   | add_4_pos_digits 
---------+------------------
       1 |           1.0001
     1.1 |          1.10001
    1.01 |         1.010001
 1.00001 |      1.000010001
(4 rows)