我在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)")
希望在数据库中找到lat值为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 }
答案 0 :(得分:4)
错误是因为没有round
的形式,它将两个numeric
作为参数。它需要numeric
和int
,其中int
是要舍入的地方数。
所以,试试这个:
Location.find_by_sql("SELECT * FROM locations WHERE ROUND(lat, 5) = 30.67036")
以下是relevant doc(搜索round
)。
另请注意,我略微调整了表达式的右侧。鉴于你在寻找
30.6703649
,舍入到小数点后第五位,即30.67036
,因为下一个数字是4,表示它将向下舍入。
此外,关于您的第一组数字,要使71.233434
等于71.233545
,您需要舍入到小数点后第3位并检查71.233
。< / p>
我建议您确定要在值中支持的容差 - 即小数点后三位或第五位 - 然后在调用round
时使用该参数。