当前位置:  开发笔记 > 编程语言 > 正文

用于计算坐标接近度的SQL查询

如何解决《用于计算坐标接近度的SQL查询》经验,为你挑选了1个好方法。

我正在使用此公式来计算我的(我的)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个条目等.

我写这篇文章主要是为了自己,但总是欢迎改进.:)

注意:如下面的Valerion所述,这以千米为单位计算.用适当的替代号码代替6371 以使用米,英里等.



1> 小智..:

对于不支持trig的数据库(例如SQLite),您可以使用pythagorus.即使您的数据库确实支持trig,pythagorus也要快得多.警告是:

你需要在x,y网格中存储坐标而不是(或者)lat,lng;

该计算假定为"扁平地球",但这对于相对本地的搜索来说是好的.

这是我正在研究的Rails项目的一个例子(重要的是中间的SQL):

class User < ActiveRecord::Base
  ...
  # has integer x & y coordinates
  ...

  # Returns array of {:user => , :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

推荐阅读
虎仔球妈_459
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有