精度与单位的硬约束
金额一律用整数最小单位(分)或 DECIMAL 定点数存储,禁止 FLOAT、DOUBLE 参与金额计算,因为二进制浮点无法精确表示 0.1 这类十进制小数,累加与分摊后会留下无法解释的尾差。比率、统计量可以用浮点,但要在字段名或注释里带单位与精度说明。「元」和「分」混用是数仓里最典型的事故来源,单位约定属于口径的一部分,必须写进建模规范。
基本信息
| 金额 | DECIMAL(18,2) 或整数分(bigint) |
|---|---|
| 比率 | DOUBLE,注释写清分子分母 |
| 物理量 | 重量、体积等需带单位后缀 |
| 命名约定 | 字段名体现单位:_cent、_kg、_rate |
| 禁止事项 | FLOAT、DOUBLE 参与金额计算 |
典型使用场景
- 支付、账单、结算类事实表统一定义金额单位并写入字段注释
- 跨系统对接前先核对对方金额单位,再做乘 100 或除 100 的换算
- 分摊、按比例拆分金额时用定点数计算,尾差按约定并入指定行
- 汇率折算用 DECIMAL 并约定保留位数与舍入规则
- 新建字段评审时排查无单位的裸数字字段
定义与展示
定义与展示
-- 金额用整数分存储,注释写明单位
CREATE TABLE fact_pay (
pay_id string,
amount_cent bigint COMMENT '支付金额,单位:分',
fee_cent bigint COMMENT '手续费,单位:分',
fx_rate decimal(18,6) COMMENT '折算汇率,保留 6 位'
) STORED AS ORC;
-- 折算到元放在展示层,避免明细里反复乘除
SELECT pay_id, amount_cent / 100.0 AS amount_yuan FROM fact_pay;类型选择对照
| 类型 | 适用对象 | 风险 |
|---|---|---|
| DECIMAL | 金额、汇率等精确数值 | 保留位数不足时舍入累积 |
| BIGINT 分 | 金额的最小单位存储 | 换算遗漏会放大百倍 |
| DOUBLE | 比率、统计量 | 参与金额计算产生尾差 |
| 无单位数值 | 命名未体现单位 | 与上游不一致时静默错数 |
分摊与按比例拆分要在最后一层处理尾差:把差额并入排序首行或金额最大的行,保证拆分后合计与原值相等,并把规则写入口径文档。
不同引擎的 DECIMAL 默认舍入规则可能不同;跨引擎比对金额时若差异只出现在分位,先确认舍入方式,而不是直接判定数据错误。