You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spark SQL中cast(decimal(38,16))小数位数保留异常问题求助

问题解决:Spark SQL中AVG结果转Decimal丢失小数位的问题

问题根源

原代码中365.25/12属于Double类型浮点运算,导致CASE表达式的返回值为Double。Spark的AVG函数对Double类型计算后,返回结果仍为Double——而Double的有效精度限制(约15-17位有效数字)会导致你的场景中计算结果仅保留10位有效小数,后续转Decimal(38,16)时只能用零填充剩余位数。

当移除除法操作时,datediff返回整数,CASE表达式结果为整数,AVG会自动切换为高精度Decimal类型计算,因此转Decimal(38,16)能保留完整小数位。

解决方案

将所有参与运算的常量转换为Decimal类型,确保整个计算流程在Decimal精度下执行,避免Double类型的精度丢失。

修改后代码示例(推荐用精确常量)

因为365.25/12 = 30.4375是精确值,直接使用该Decimal常量可以简化计算并保证精度:

cast(
    AVG(
        CASE WHEN 
            a.is_debtor = 1 AND 
            a.is_kk = 0 AND 
            a.is_open = 0 
        THEN CAST(datediff((a.date_end_plan + interval '1 day'), a.date_start) AS DECIMAL(38,16)) / CAST(30.4375 AS DECIMAL(38,16))
        END
    ) as decimal(38,16)
) AS avg_term_plan_closed

保留原式结构的修改

如果需要保留原式的除法逻辑,将所有常量转为Decimal即可:

cast(
    AVG(
        CASE WHEN 
            a.is_debtor = 1 AND 
            a.is_kk = 0 AND 
            a.is_open = 0 
        THEN CAST(datediff((a.date_end_plan + interval '1 day'), a.date_start) AS DECIMAL(38,16)) / (CAST(365.25 AS DECIMAL(38,16)) / CAST(12 AS DECIMAL(38,16)))
        END
    ) as decimal(38,16)
) AS avg_term_plan_closed

验证逻辑

修改后,CASE内的所有运算都在Decimal(38,16)精度下执行,AVG函数会基于Decimal类型计算平均值,最终转换后的结果就能保留完整的16位小数,与期望输出一致。

内容的提问来源于stack exchange,提问作者Егор Бугаков

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 00:37:39