Postgres / Rails Active Record -- 查询舍入浮点值

Sas*_*sha 3 sql postgresql activerecord ruby-on-rails ruby-on-rails-4

我在 Rails 应用程序中使用 Postgres。将纬度/经度作为浮点值存储在数据库中。我希望能够比较位置的纬度/经度,但我只知道如何做到完全相等:

Location.where(lat: @lat, lon: @lon)
Run Code Online (Sandbox Code Playgroud)

我的问题是,我希望 Postgres 读取,比如 71.233434 等于 71.233545,或者其他什么。换句话说,我可以查询舍入相等或范围内的相等吗?

我已经在 Google 上进行了相当广泛的搜索(也许使用了错误的术语?我想不出它。“Active Record Postgres float inside”,“Active Record Postgres rounded query”等)。但运气不好。我只找到了如何对来自数据库的值进行舍入,这没有多大帮助,因为这在 Ruby 中很容易做到。

有任何想法吗?我更喜欢某种 Active Record 解决方案(如果存在),但如果不存在,我也绝对会欣赏(指向)实际查询代码的链接。

谢谢!

编辑- 看着这个答案,我尝试了以下操作:

Location.find_by_sql("SELECT * FROM locations WHERE lat = ROUND(30.67035, 0.001)")
Run Code Online (Sandbox Code Playgroud)

希望在数据库中找到纬度值为 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)
Run Code Online (Sandbox Code Playgroud)

当我尝试相反的方法时,基本上会出现相同的错误,这更有意义:

Location.find_by_sql("SELECT * FROM locations WHERE ROUND(lat, 0,001) = 30.67035")
Run Code Online (Sandbox Code Playgroud)

我的回答基于以下回复:

  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 }
Run Code Online (Sandbox Code Playgroud)

kha*_*son 5

该错误是因为没有任何形式round以两个numerics 作为参数。它需要 anumeric和 an int,其中 theint是要舍入的位数。

所以,试试这个:

Location.find_by_sql("SELECT * FROM locations WHERE ROUND(lat, 5) = 30.67036")
Run Code Online (Sandbox Code Playgroud)

这是相关文档(搜索round)。

另请注意,我稍微调整了表达式的右侧。如果您要查找 30.6703649,四舍五入到小数点后第五位,则为30.67036,因为下一位数字是 4,这意味着它将向下舍入。

另外,关于您的第一组数字,为了71.233434被视为等于71.233545,您需要四舍五入到小数点后第三位并检查71.233

我建议您确定要在值中支持的容差(即小数点后第三位或第五位),然后在调用中使用该参数round