Как избежать PG:: NumericValueOutOfRange при использовании функции суммы
У меня есть такой способ:
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
Когда столбец равен decimal
, он возвращает значение без проблем.
Но когда столбец integer
, метод заканчивается ошибкой PG::NumericValueOutOfRange
.
Следует ли мне изменить тип столбца integer
на decimal
, или есть способ получить результат sum
без изменения типа столбца?
Ответы
Ответ 1
Вы можете указать свое значение так, чтобы оно было десятичным значением, поэтому не нужно изменять тип столбца:
sql = "SUM(#{column} * CAST(market_cap as decimal(53,8))) / SUM(CAST(market_cap as decimal(53,8))) as weighted_average"
P.S. Я бы пошел с изменением типа столбца - он последователен, затем.
Ответ 2
Вы всегда можете сделать 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
Ответ 3
Я бы предложил вам изменить тип данных на decimal
. Потому что, когда SUM получает PG::NumericValueOutOfRange
, это означает, что вашего типа данных недостаточно. Это приведет к изящному решению этого сценария, а не к обходному пути.
Ответ 4
Документация Postgres говорит об этом в виде возвращаемого типа SUM():
bigint для аргументов smallint или int, числовых аргументов bigint, в противном случае то же самое, что и тип данных аргумента
Это означает, что вам нужно каким-то образом изменить тип данных, который вы передадите SUM. Это может быть одно из следующего:
- Изменить таблицу для изменения типа данных столбца.
- Вставьте столбец в другой тип данных в свой метод.
- Создайте представление, в котором все целые столбцы будут числиться и будут использоваться в вашем методе.
Ответ 5
Вы пытаетесь поместить десятичное значение в целочисленный параметр. Если вы не используете значение ABS(), которое будет невозможно, если вы на 100% не уверены, что значение% всегда будет 0.
Используйте тип Float или функцию ABS(), если у вас есть INT
Ответ 6
Yo может попробовать лить колонку в десятичный
sql = "SUM(CAST(#{column}) AS DECIMAL * market_cap) / SUM(market_cap) as weighted_average"