[英]How to avoid PG::NumericValueOutOfRange when using sum function
I have method like this: 我有这样的方法:
def self.weighted_average(column)
sql = "SUM(#{column} * market_cap) / SUM(market_cap) as weighted_average"
Company.select(sql).to_a.first.weighted_average
end
When the column is a decimal
, it returns a value without problem. 当列是
decimal
,它返回一个没有问题的值。 But when the column is integer
, the method ends up with a PG::NumericValueOutOfRange
error. 但是当列是
integer
,该方法最终会出现PG::NumericValueOutOfRange
错误。
Should I change column type integer
to decimal
, or is there a way to get the result of sum
without changing column type? 我应该将列类型
integer
更改为decimal
,还是有办法在不更改列类型的情况下获得sum
的结果?
You can always make float
from your integer. 你总是可以从整数中
float
。
def self.weighted_average(column)
column = column.to_f
sql = "SUM(#{column} * market_cap) / SUM(market_cap) as weighted_average"
Company.select(sql).to_a.first.weighted_average
end
I would suggest you to change the datatype to decimal
. 我建议你将数据类型更改为
decimal
。 Because, when SUM gets PG::NumericValueOutOfRange
, it means that your datatype is not sufficient. 因为,当SUM获取
PG::NumericValueOutOfRange
,这意味着您的数据类型不足。 It will lead to gracefully handle this scenario, instead of a workaround. 它将导致优雅地处理此方案,而不是解决方法。
You can cast your value to alway be a decimal value, thus no need to change the column type: 您可以将值转换为小数值,因此无需更改列类型:
sql = "SUM(#{column} * CAST(market_cap as decimal(53,8))) / SUM(CAST(market_cap as decimal(53,8))) as weighted_average"
PS I would go with changing the column type - it is consistent then. PS我会改变列类型 - 它是一致的 。
Postgres documentation says this about SUM() return type: Postgres文档说这个关于SUM()返回类型:
bigint for smallint or int arguments, numeric for bigint arguments, otherwise the same as the argument data type
smallint或int参数的bigint,bigint参数的numeric,否则与参数数据类型相同
This means that you will somehow need to change datatype that you pass to SUM. 这意味着您将以某种方式需要更改传递给SUM的数据类型。 It can be one of the following:
它可以是以下之一:
You are trying to place a decimal value into a integer parameter. 您正在尝试将十进制值放入整数参数。 Unless you use the ABS() value that will not be possible, unless you are 100% sure that the % value will always be 0.
除非您使用无法实现的ABS()值,否则除非您100%确定%值始终为0。
Use type Float or function ABS() if you HAVE to have an INT 如果您必须拥有INT,请使用类型Float或函数ABS()
哟可以尝试将列转换为十进制
sql = "SUM(CAST(#{column}) AS DECIMAL * market_cap) / SUM(market_cap) as weighted_average"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.