【问题标题】:Redshift numeric precision truncatingRedshift 数值精度截断
【发布时间】:2019-03-06 15:28:22
【问题描述】:

我遇到了无法解释 Redshift 如何处理 SUM 划分的情况。

有示例表:

create table public.datatype_test(
a numeric(19,6),
b numeric(19,6));
insert into public.datatype_test values(222222.2222, 333333.3333);
insert into public.datatype_test values(444444.4444, 666666.6666);

现在我尝试运行查询:

select sum(a)/sum(b) from public.datatype_test;

我得到结果 0.6666(4 位小数)。它与工具显示无关,它实际上只返回 4 位小数,与表格中的数字大小无关。就我而言,4 位小数不够精确。 如果我使用 AVG 而不是 SUM,情况也是如此。

如果我使用 MAX 而不是 SUM,我会得到:0.6666666666666666666(19 位小数)。

当不使用物理表时,它也会返回正确的结果(0.6666666666666667):

with t as (
select 222222.2222::numeric(19,6) as a, 333333.3333::numeric(19,6) as b union all 
select 444444.4444::numeric(19,6) as a, 666666.6666::numeric(19,6) as b
)
select sum(a)/sum(b) as d from t; 

我查看了有关 SUM 和 Computations with Numeric Values 的 Redshift 文档,但根据文档我仍然没有得到结果。

对表格列使用浮点数据类型不是一种选择,因为我需要存储精确的货币金额,而 15 位有效数字是不够的。

对 SUM 聚合使用强制转换也可以得到 0.6666666666666666666(19 位小数)。

select sum(a)::numeric(19,6)/sum(b) from public.datatype_test;

但它看起来不对,我不能强迫 BI 工具做这种变通方法,而且使用这些数据的每个人都不应该使用这种变通方法。

我尝试在 PostgreSQL 10 中使用相同的测试,它可以正常工作,返回足够数量的小数进行除法。

我可以对数据库设置做些什么来避免在 SQL Query 中进行强制转换吗? 非常感谢任何建议或指导。

红移版本: i686-pc-linux-gnu 上的 PostgreSQL 8.0.2,由 GCC gcc (GCC) 3.4.2 20041017 (Red Hat 3.4.2-6.fc3)、Redshift 1.0.4081 编译 使用 dc2.8xlarge 节点

【问题讨论】:

  • 我建议您联系 AWS 支持并提供此信息

标签: sql amazon-redshift


【解决方案1】:

我也遇到过类似的问题,虽然我没有不需要变通办法的解决方案,但我至少可以解释一下。

除法结果的精度/小数位数由“数值计算”文档中的规则定义。

这些规则的结果是decimal(19,6) 除以另一个decimal(19,6) 将返回decimal(38,19)。

不过,发生在您身上的是 MAX 返回与基础列相同的精度/比例,但 SUM 无论如何都会返回 decimal(38,*)。 (这可能是防止“大数据”总和溢出的安全预防措施)。如果将decimal(38,6) 除以另一个,则得到decimal(38,4)。

AWS 支持可能不会认为这是一个缺陷——没有关于如何处理除法中的小数精度的 SQL 标准,并且鉴于这是记录在案的行为,这可能是一个深思熟虑的决定。

解决此问题的唯一方法是对分子进行类型转换,或将其乘以 sum(a) * cast(1 as decimal(10,9)) 之类的东西,这是可移植的 SQL,并且会强制分子中有更多小数位,从而导致结果。

为方便起见,我在JSFiddle with the rules 中制作了一个计算器,以便您可以尝试不同的选项:

scale = Math.max(4, s1 + p2 - s2 + 1)
precision = p1 - s1 + s2 + scale

if (precision > 38) {
    scale = Math.max((38 + scale - precision), 4)
    precision = 38
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-13
    • 2017-10-02
    • 1970-01-01
    • 1970-01-01
    • 2014-08-16
    相关资源
    最近更新 更多