舍入一个分裂的商?

时间:2014-05-14 19:00:20

标签: sql postgresql rounding

我试图在select语句中划分两列,然后将商舍入到4位小数。

select round(round(sum(case when acct_no = '2999' 
      and date between '1/1/14' and current_date then amount end)::numeric, 4)::float
 / round(sum(case when acct_no = '3989' 
      and date between '1/1/14' and current_date then amount end)::numeric, 4)::numeric, 4) column
from table

查询的其余部分将包含多个日期,因此其中的日期应该是必要的。

它给出的错误:

  

错误:函数round(双精度,整数)不存在

这是在PostgreSQL中尝试的。

2 个答案:

答案 0 :(得分:4)

SELECT round((
          sum(CASE WHEN acct_no = '2999' 
              AND thedate between '2014-1-1' AND current_date THEN amount END)
        / sum(CASE WHEN acct_no = '3989' 
              AND thedate between '2014-1-1' AND current_date THEN amount END)
       )::numeric, 4) AS result
FROM   tbl;
  • Postgres中的浮点类型没有添加精度修饰符的函数round()。仅适用于numericas per documentation

  • 将浮点数除以numeric会产生double precisionfloat8)。测试:

    SELECT 5::float/3::numeric  -- result is double precision
    
  • 在计算结束时将舍入一次。这更快,更准确。

  • 切勿使用date作为列名。它是标准SQL中的保留字和Postgres中的基本类型。

  • 最好在代码中使用日期文字中的recommended ISO 8601 date format。无论设置和区域设置如何,这都有效,而本地格式会因不同的设置而中断。

如果不是您提到的rest of the query,则可以进一步简化:

SELECT round((   sum(CASE WHEN acct_no = '2999' THEN amount END)
        / NULLIF(sum(CASE WHEN acct_no = '3989' THEN amount END), 0)
       )::numeric, 4) AS result
FROM   tbl
WHERE  thedate between '2014-1-1'::date AND current_date;

最后,这也使用除数上的NULLIF()来捕获“除以0”异常。

答案 1 :(得分:3)

我重新格式化了您的示例代码,以便更轻松地理解它:

select  round(
            round(
                sum(
                    case
                        when    acct_no = '2999'
                                and date between '1/1/14' and current_date then amount
                    end )::numeric,
                4 )::float
            / round(
                sum(
                    case
                        when    acct_no = '3989'
                                and date between '1/1/14' and current_date then amount
                    end )::numeric,
                4 )::numeric,
            4 ) column
from table

问题在于您将分部操作的分子转换为float数据类型which, because you didn't specify a precision, is equivalent to double precision

round(
    sum(
        case
            when    acct_no = '2999'
                    and date between '1/1/14' and current_date then amount
        end )::numeric,
    4 )::float
/ round(
    sum(
        case
            when    acct_no = '3989'
                    and date between '1/1/14' and current_date then amount
        end )::numeric,
    4 )::numeric

因此,表达式的结果是double precision值而不是numeric值,因此您观察到的错误。