Postgres / Rails Active Record - 查询四舍五入的浮点值
Posted
技术标签:
【中文标题】Postgres / Rails Active Record - 查询四舍五入的浮点值【英文标题】:Postgres / Rails Active Record -- query for rounded float value 【发布时间】:2014-11-13 23:42:16 【问题描述】:我在 Rails 应用程序中使用 Postgres。将 Lat/Lon 作为浮点值存储在数据库中。我希望能够比较位置的纬度/经度,但我只知道如何进行精确相等:
Location.where(lat: @lat, lon: @lon)
我的问题是,我希望 Postgres 读取,比如 71.233434 等于 71.233545,或者其他什么。换句话说,我可以查询四舍五入的相等性,还是范围内的相等性?
我已经在谷歌上搜索了很多内容(可能使用了错误的术语?我想不出来。“Active Record Postgres 浮动范围内”、“Active Record Postgres 圆形查询”等)。不过,没有运气。我只找到了round values coming out of the database 的方法,这并没有多大帮助,因为这在 Ruby 中很容易做到。
有什么想法吗?如果存在,我更喜欢某种 Active Record 解决方案,但如果不存在,我也肯定会感谢(链接到)实际查询代码。
谢谢!
编辑 -- 查看this answer,我尝试了以下操作:
Location.find_by_sql("SELECT * FROM locations WHERE lat = ROUND(30.67035, 0.001)")
希望在数据库中找到纬度值为 30.6703649 的位置,但我遇到了这个错误:
ActiveRecord::StatementInvalid: PG::UndefinedFunction: ERROR: function round(numeric, numeric) does not exist
LINE 1: SELECT * FROM places WHERE lat = ROUND(30.67035, 0.001)
当我尝试相反时,基本相同的错误,这更有意义:
Location.find_by_sql("SELECT * FROM locations WHERE ROUND(lat, 0,001) = 30.67035")
我的回答基于以下回复:
scope :none, -> where('1=2') # returns an empty relation
scope :by_ll, -> (lat, lon) by_lat(lat).by_lon(lon)
scope :by_lat, -> (lat) lat ? where("ROUND( CAST(lat as numeric), 4 ) = ?", lat.round(4) ) : none
scope :by_lon, -> (lon) lon ? where("ROUND( CAST(lon as numeric), 4 ) = ?", lon.round(4) ) : none
【问题讨论】:
【参考方案1】:错误是因为没有round
的形式将两个numeric
s 作为参数。它需要一个numeric
和一个int
,其中int
是要四舍五入的位置数。
那么,试试这个:
Location.find_by_sql("SELECT * FROM locations WHERE ROUND(lat, 5) = 30.67036")
这里是relevant doc(搜索round
)。
还请注意,我稍微调整了表达式的右侧。鉴于您正在寻找
30.6703649
,四舍五入到小数点后5位,即30.67036
,因为下一位是4,表示要向下舍入。
另外,关于您的第一组数字,要使 71.233434
被视为等于 71.233545
,您需要四舍五入到小数点后第三位并检查 71.233
。
我建议您确定要在值中支持的容差(即小数点后 3 位或第 5 位),然后在调用 round
时使用该参数。
【讨论】:
非常感谢!那钉了它。作为记录,我还必须将 lat/lon 值(即 DP 值)转换为 Numerics。我已将最终结果放在上面的问题中。 您正在比较 DB 的四舍五入到 1/10 的幂和 ruby 的四舍五入到 1/10 的幂。我怀疑有时可能会以不同的方式舍入相同的值,特别是因为 1/10 的幂在二进制浮点中没有精确表示!我会尝试像ROUND(lat, 5) = ROUND(?, 5)
这样的方法来做同样的事情(未经测试)。以上是关于Postgres / Rails Active Record - 查询四舍五入的浮点值的主要内容,如果未能解决你的问题,请参考以下文章
Rails 和 Postgres:迁移到 change_colomn 时出现错误“无法强制转换为没有时区的时间戳”
rails - postgres 或 rails 是不是自动验证 datetime 列只能具有 datetime 对象?