我正在使用此公式来计算我的(我的)SQL数据库中具有十进制格式的纬度和经度字段的条目之间的距离:
6371 * ACOS(SIN(RADIANS( %lat1% )) * SIN(RADIANS( %lat2% )) + COS(RADIANS( %lat1% )) * COS(RADIANS( %lat2% )) * COS(RADIANS( %lon2% ) - RADIANS( %lon1% )))
适当地替换%lat1%和%lat2%它可以在WHERE子句中用于查找另一个条目的某个半径内的条目,在ORDER BY子句中使用它与LIMIT一起将找到最近的x个条目等。 / p>
我写这篇文章主要是为了自己,但总是欢迎改进。 :)
注意:如下面的Valerion所述,这以千米计算。用appropriate alternative number代替6371以使用米,英里等。
答案 0 :(得分:7)
对于不支持trig的数据库(例如SQLite),您可以使用pythagorus。即使您的数据库确实支持trig,pythagorus也要快得多。警告是:
这是我正在研究的Rails项目的一个例子(重要的是中间的SQL):
class User < ActiveRecord::Base
...
# has integer x & y coordinates
...
# Returns array of {:user => <User>, :distance => <distance>}, sorted by distance (in metres).
# Distance is rounded to nearest integer.
# point is a Geo::LatLng.
# radius is in metres.
# limit specifies the maximum number of records to return (default 100).
def self.find_within_radius(point, radius, limit = 100)
sql = <<-SQL
select id, lat, lng, (#{point.x} - x) * (#{point.x} - x) + (#{point.y} - y) * (#{point.y} - y) d
from users where #{(radius ** 2)} >= d
order by d limit #{limit}
SQL
users = User.find_by_sql(sql)
users.each {|user| user.d = Math.sqrt(user.d.to_f).round}
return users
end
答案 1 :(得分:2)
我是否认为这是Haversine公式?
答案 2 :(得分:1)
我在车辆跟踪应用程序中使用完全相同的方法并且已经做了多年。它运作得非常好。快速检查一些旧代码显示我将结果乘以6378137,如果内存服务转换为米,但我很长时间没有触及它。
我相信SQL 2008有一个新的空间数据类型,我想这可以在不知道这个公式的情况下进行这些比较,并且还允许可能有趣的空间索引,但我没有研究过它。
答案 3 :(得分:1)
我一直在使用它,忘了我得到它的地方。
SELECT n, SQRT(POW((69.1 * (n.field_geofield_lat - :lat)) , 2 ) + POW((53 * (n.field_geofield_lon - :lon)), 2)) AS distance FROM field_revision_field_geofield n ORDER BY distance ASC