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. But when the column is integer
, the method ends up with a PG::NumericValueOutOfRange
error.
Should I change column type integer
to decimal
, or is there a way to get the result of sum
without changing column type?
6 Answers
Answers 1
You can always make float
from your integer.
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
Answers 2
I would suggest you to change the datatype to decimal
. Because, when SUM gets PG::NumericValueOutOfRange
, it means that your datatype is not sufficient. It will lead to gracefully handle this scenario, instead of a workaround.
Answers 3
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"
P.S. I would go with changing the column type - it is consistent then.
Answers 4
Postgres documentation says this about SUM() return type:
bigint for smallint or int arguments, numeric for bigint arguments, otherwise the same as the argument data type
This means that you will somehow need to change datatype that you pass to SUM. It can be one of the following:
- Alter table to change column datatype.
- Cast column to other datatype in your method.
- Create a view that casts all integer columns to numeric and use that in your method.
Answers 5
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.
Use type Float or function ABS() if you HAVE to have an INT
Answers 6
Yo could try casting column to decimal
sql = "SUM(CAST(#{column}) AS DECIMAL * market_cap) / SUM(market_cap) as weighted_average"
0 comments:
Post a Comment