【问题标题】:How to avoid PG::NumericValueOutOfRange when using sum function使用 sum 函数时如何避免 PG::NumericValueOutOfRange
【发布时间】:2016-09-14 08:17:22
【问题描述】:

我有这样的方法:

  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 的结果?

【问题讨论】:

    标签: sql ruby-on-rails postgresql


    【解决方案1】:

    你总是可以从你的整数中生成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
    

    【讨论】:

    • column 是模型的列名。那只是StringSymbol
    【解决方案2】:

    您可以将您的值始终转换为十进制值,因此无需更改列类型:

    sql = "SUM(#{column} * CAST(market_cap as decimal(53,8))) / SUM(CAST(market_cap as decimal(53,8))) as weighted_average"
    

    附:我会改变列类型 - 它是一致的然后。

    【讨论】:

      【解决方案3】:

      我建议您将数据类型更改为decimal。因为,当 SUM 得到PG::NumericValueOutOfRange 时,说明你的数据类型不够用。它将导致优雅地处理这种情况,而不是解决方法。

      【讨论】:

      • 列中的所有值对于integer来说都足够小,我只在使用SQL的计算函数时得到错误。如果可能,我想避免更改列类型。
      【解决方案4】:

      Postgres documentation 这样说 SUM() 返回类型:

      bigint 用于 smallint 或 int 参数, numeric 用于 bigint 参数, 否则与参数数据类型相同

      这意味着您将需要更改传递给 SUM 的数据类型。它可以是以下之一:

      • 更改表以更改列数据类型。
      • 在您的方法中将列转换为其他数据类型。
      • 创建一个将所有整数列转换为数字的视图,并在您的方法中使用它。

      【讨论】:

        【解决方案5】:

        您正在尝试将十进制值放入整数参数中。除非您使用不可能的 ABS() 值,除非您 100% 确定 % 值将始终为 0。

        如果你必须有一个 INT,请使用浮点类型或函数 ABS()

        【讨论】:

          【解决方案6】:

          你可以尝试将列转换为十进制

          sql = "SUM(CAST(#{column}) AS DECIMAL * market_cap) / SUM(market_cap) as weighted_average"
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-02-15
            • 2020-01-17
            • 2019-10-20
            • 1970-01-01
            • 2018-05-19
            • 2020-01-26
            • 1970-01-01
            相关资源
            最近更新 更多