【问题标题】:Rounding the quotient of a division?四舍五入除法的商?
【发布时间】:2014-05-14 19:00:19
【问题描述】:

我试图在 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 中尝试的。

【问题讨论】:

  • 看起来应该可以了!您是否尝试过强制转换而不是 ::numeric,例如: cast(... as numeric) ?此外,您可以尝试将“数量”合并为 0 或其他内容(以防它返回 null)(例如 coalesce(amount,0::expectedtype))
  • 目前它正在工作,但唯一的问题是它没有四舍五入。小数点后仍有 14 个数字。
  • 那是因为回合需要在除法之后进行。不在单个分子和分母上。 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)我认为从本质上讲,您的说法是 22.0000 到 4,然后 7.000 到 4,然后将两者除以...3.1428571...但不要四舍五入。
  • 哦,我没有意识到问题是数字没有四舍五入,我以为它收到了错误消息。是的,确实,如果你想要四舍五入的结果(@xQbert),你需要在 round() / round() 周围再换一个“round”。
  • 好的,现在这是我收到相关错误的时候了。我将在问题中添加另一轮。错误(如前所述)是函数轮(双精度,整数)不存在

标签: sql postgresql rounding


【解决方案1】:
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 precision (float8)。测试:

      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”异常。

【讨论】:

    【解决方案2】:

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

    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 值,因此您观察到的错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-13
      • 1970-01-01
      • 1970-01-01
      • 2023-01-12
      • 2012-08-04
      • 2023-03-26
      相关资源
      最近更新 更多