Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. 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?

like image 618
ironsand Avatar asked Sep 14 '16 08:09

ironsand


4 Answers

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
like image 87
Bartłomiej Gładys Avatar answered Nov 09 '22 18:11

Bartłomiej Gładys


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.

like image 25
Andrey Deineko Avatar answered Nov 09 '22 17:11

Andrey Deineko


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.

like image 2
Venkataraman R Avatar answered Nov 09 '22 16:11

Venkataraman R


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.
like image 2
jva Avatar answered Nov 09 '22 17:11

jva