在 Amazon Redshift 中存储极小的值
Posted
技术标签:
【中文标题】在 Amazon Redshift 中存储极小的值【英文标题】:Storing extremely small values in Amazon Redshift 【发布时间】:2017-03-10 17:31:25 【问题描述】:我正在使用以下命令在Amazon Redshift
中创建一个表:
CREATE TABLE asmt.incorrect_question_pairs_unique
AS
SELECT question1,
question2,
occurrences,
occurrences / (SUM(occurrences)::FLOAT) OVER () AS prob_q1_q2
FROM (SELECT question1,
question2,
SUM(occurrences) AS occurrences
FROM asmt.incorrect_question_pairs
GROUP BY question1,
question2
HAVING SUM(occurrences) >= 50)
我也尝试了一个替代方案:
CREATE TABLE asmt.incorrect_question_pairs_unique
AS
SELECT question1,
question2,
occurrences,
occurrences::float / SUM(occurrences) OVER () AS prob_q1_q2
FROM (SELECT question1,
question2,
SUM(occurrences) AS occurrences
FROM asmt.incorrect_question_pairs
GROUP BY question1,
question2
HAVING SUM(occurrences) >= 50)
我希望prob_q1_q2
列成为float
列,这就是我将分母/分子转换为float
的原因。但在结果表中,我在该列中得到全零。
我想指出SUM(occurrences)
大约等于10 Billion
,因此prob_q1_q2
列将包含非常小的值。有没有办法在Amazon Redshift
中存储这么小的值?
如何确保列中的所有值都不为零float
?
任何帮助将不胜感激。
【问题讨论】:
试试occurences::float / sum() ...
不,仍然是零。
我想指出SUM(occurrences)
的数量将超过10Billion
。那么这些零是否有可能因为occurrences::float / SUM(occurrences)
太小而显示为零?
你对那里的窗口函数的意图是什么?
float
类型(8 字节)应该能够以至少 15 位的精度存储从 1E-307 到 1E+308 的值。尝试将部门的两个部分都转换为float
。 postgresql.org/docs/9.1/static/datatype-numeric.html
【参考方案1】:
方法 1 - 我也遇到了同样的问题!在我的例子中,它是数百万行,所以我将结果乘以 10000。每当我想从该列中选择值时,我都会在 select 语句中除以 10000 以使其相等。 我知道这不是完美的解决方案,但对我有用。方法 2 - 我创建了一个具有 Numeric(12,6) 数据类型的示例表,并在导入结果时设置与您的类似,我可以看到浮点值高达 6 位十进制精度。
我猜,当您使用 create table AS 命令时,转换不起作用,您需要创建指定数据类型的表,该数据类型强制将结果集存储到某个精度级别。 它很奇怪!相同的选择如何返回 0.00,但当插入具有强制列的表时,它返回 0.00333。 如果我做出了错误的假设,请发表评论,我会重新调整答案。
【讨论】:
【参考方案2】:臭虫,
您可能获得的数字太小,无法存储在 FLOAT 类型的 Amazon Redshift 中。尝试改用 DECIMAL,它不可能存储你的值,它是一个 128 位变量。
它的工作方式如下,如果值太大或在您的情况下太小并且超过您的类型的最大/最小值,则修剪最后一位数字,然后将新的(修剪的)值存储在您类型的变量/列。 当它削减一个很大的价值时,你几乎没有损失,可以说你从 200 亿美元中削减了 20 美分,你不会受到太大的伤害。但是在您的情况下,当数字太小时,您可以在修剪最后一位数字以适合类型时丢失所有内容 (例如,一个类型最多可以存储 5 位数字,并且您希望在此类型的变量/列中存储 0.000009 的值。您的值不适合该类型,因此它从最后 2 位数字中修剪,因此它可以适合并且你会收到一个新值 0.0000 )
因此,如果您按照我的想法将 ::float 更改为 ::decimal 应该可以解决您的问题。 附言十进制可能需要指定它的大小 f.e.十进制(127,100)
【讨论】:
【参考方案3】:试试:
select cast(num1 as float) / cast(num2 as float);
这将为您提供最多 2 位小数的结果(默认情况下),但会占用您的一些处理时间。做任何其他事情都会将小数部分四舍五入。
【讨论】:
即使select 10::float / 3
给出相同的结果。但在我的情况下不起作用。【参考方案4】:
You can have up to 38 digits in a DECIMAL
/NUMERIC
column with of 37 digits of scale.
CREATE TEMP TABLE precision_test (test NUMERIC(38,37)) DISTSTYLE ALL
;
INSERT INTO precision_test
SELECT CAST( 0.0000000000000000000000000000000000001 AS NUMERIC(38,37)) test
;
SELECT * FROM precision_test
;
--Returns 0.0000000000000000000000000000000000001
【讨论】:
以上是关于在 Amazon Redshift 中存储极小的值的主要内容,如果未能解决你的问题,请参考以下文章
amazon redshift 中存储的特定行的默认值在哪里?
Amazon redshift 存储过程,CONTINUE 不能在循环外使用;