为啥 Amazon Redshift 会截断此 JSON 浮点数据的精度?

Posted

技术标签:

【中文标题】为啥 Amazon Redshift 会截断此 JSON 浮点数据的精度?【英文标题】:Why is Amazon Redshift truncating the precision of this JSON float data?为什么 Amazon Redshift 会截断此 JSON 浮点数据的精度? 【发布时间】:2016-05-05 22:58:35 【问题描述】:

我发现 Amazon Redshift 将浮点数的精度截断为非常低的精度(6 位)。有没有办法解决这个问题?

例子:

SELECT
JSON_EXTRACT_PATH_TEXT('"a":123456789.5555555, "b":123456789.0', 'a')::float,
JSON_EXTRACT_PATH_TEXT('"a":123456789.5555555, "b":123456789.0', 'b')::float;

给予:

 json_extract_path_text | json_extract_path_text 
------------------------+------------------------
              123457000 |              123457000
(1 row)

将其与整数进行比较:

SELECT
JSON_EXTRACT_PATH_TEXT('"a":123456789, "b":123456789', 'a')::float,
JSON_EXTRACT_PATH_TEXT('"a":123456789, "b":123456789', 'b')::float;

结果:

 json_extract_path_text | json_extract_path_text 
------------------------+------------------------
              123456789 |              123456789
(1 row)

看起来float应该有更高的精度,而不是更少!!!

感谢您的任何见解。

【问题讨论】:

为什么分析数据库需要如此精确?无论如何,您将要做 AVG 和其他不需要如此高精度的统计函数。 【参考方案1】:

问题不是 Redshift 本身的 FLOAT 精度,而是解析出来的 JSON 数的精度。如果我们在不进行任何转换的情况下查询 JSON……

SELECT JSON_EXTRACT_PATH_TEXT('"a":123456789.5555555', 'a');

…导致这个 VARCHAR 值:

"1.23457e+08"

因此,任何后续到 FLOAT 的转换只能使用这个已经不准确的值。

一种解决方法是将 JSON 中的数字存储为字符串……

SELECT JSON_EXTRACT_PATH_TEXT('"a":"123456789.5555555"', 'a')::float;
↓
123456789.55555549

如果需要更高的精度,可以使用到DECIMAL 数据类型的转换...

SELECT JSON_EXTRACT_PATH_TEXT('"a":"123456789.5555555", "b":123456789.0', 'a')::decimal(20, 10)
↓
123456789.5555555000

或者,您也可以实现 User-Defined Function,您可以在其中以更高的精度自行解析 JSON。

【讨论】:

以上是关于为啥 Amazon Redshift 会截断此 JSON 浮点数据的精度?的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 SQL Workbench/J 在 Amazon Redshift 中创建新用户

AWS:将日志从 Amazon CloudWatch 导出到 Amazon Redshift

Redshift 截断表并重置身份?

将数据从 Amazon S3 复制到 Redshift 并避免重复行

[Amazon](500310) 无效操作:"$$" 处或附近未终止的美元引号字符串

Amazon Redshift 是不是支持扩展 dblink?