【问题标题】:Casting `sum` result to an integer in Ecto将“sum”结果转换为 Ecto 中的整数
【发布时间】:2017-12-21 11:43:34
【问题描述】:

我在 Ecto 中有一个查询,包括包含整数的列的总和。我使用 MySQL 作为数据库。

例如

result = Repo.one(
  from v in Vote,
    where: [post_id: 1],
    select: sum(v.direction)
)

IO.inspect(result)

# Yields: #Decimal<5>

结果从 Ecto 返回为 #Decimal&lt;x&gt;。当我将其编码为 json 时,它会转换为字符串。理想情况下,我希望它是一个整数,特别是因为结果将始终是数据库中的一个整数。

投射这个的最佳方式是什么?

这是我的架构:

schema "votes" do
  field :direction, :integer

  belongs_to :user, Linklet.User
  belongs_to :link, Linklet.Link

  timestamps()
end

我已经设法通过在片段中使用 MySQL 的 CONVERT 函数来实现预期的结果,但这似乎不是最可靠的方法:

result = Repo.one(
  from v in Vote,
    where: [post_id: 1],
    select: fragment("CONVERT(?, SIGNED)", sum(v.direction))
)

有没有更好的办法?

【问题讨论】:

  • 如果你希望它是整数,为什么不首先将它作为整数存储在数据库中呢?另外,请显示Vote 的架构文件。
  • Decimal.to_integer(result)?
  • @mudasobwa direction 列是一个整数。我不确定为什么结果是小数。架构已发布
  • @Dogbert 理想情况下,我希望在查询时进行类型转换以避免映射结果。
  • 是的,它也在迁移中声明为整数。我检查了数据库本身,它是一个整数。也许这是一个mysql的东西......

标签: elixir ecto


【解决方案1】:

您可以使用Ecto.Query.type/2 在数据库级别转换为整数:

result = Repo.one(
  from v in Vote,
  where: [post_id: 1],
  select: type(sum(v.direction), :integer)
)

【讨论】:

  • 您应该提到这可能不是旧 ecto 库的功能
【解决方案2】:

MySQL 中的SUM 为整数输入返回一个DECIMAL 值。

SUM() 和 AVG() 函数为精确值参数(整数或 DECIMAL)返回 DECIMAL 值,为近似值参数(FLOAT 或 DOUBLE)返回 DOUBLE 值。

Source

所以你有两个选择:要么像你已经在做的那样将值转换为 SIGNED,要么在 Elixir 中使用 Decimal.to_integer/1 将 Decimal 值转换为整数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-12
    • 2021-03-22
    • 2011-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-23
    相关资源
    最近更新 更多