距离内的 Oracle 空间搜索

标签 oracle search geo oracle-spatial

我有下表城市:

ID(int),City(char),latitude(float),longitude(float).

现在根据用户的经度(例如:44.8)和纬度(例如:46.3),我想搜索他附近 100 英里/公里内的所有城市。

我找到了一些示例,但不知道如何使它们适应我的情况
select *
from GEO.Cities a
where SDO_WITHIN_DISTANCE([I don`t know],
MDSYS.SDO_GEOMETRY(2001, 8307, MDSYS.SDO_POINT_TYPE(44.8,46.3, NULL) ,NULL, NULL), 
'distance = 1000') = 'TRUE';

任何帮助,将不胜感激。

P.S:如果有可能有距离和排序

P.P.S:由于性能问题,我想这样做,我已经这样做了 http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL但是时间太长了……

最佳答案

您对 mySQL 距离搜索有很好的引用。

忘记 Oracle Spatial 的东西。太多的代码,太多的复杂性,没有足够的附加值。

这是一个可以解决问题的查询。这使用法定英里的距离。 编辑 这修复了 mdarwin 提到的错误,如果您尝试将其用于北极或南极的位置,则会以划分检查为代价。

  SELECT id, city, LATITUDE, LONGITUDE, distance
    FROM
  (
    SELECT id, 
           city, 
           LATITUDE, LONGITUDE,
           (3959 * ACOS(COS(RADIANS(LATITUDE)) 
                 * COS(RADIANS(mylat)) 
                 * COS(RADIANS(LONGITUDE) - RADIANS(mylng)) 
                 + SIN(RADIANS(LATITUDE)) 
                 * SIN(RADIANS(mylat)) 
               ))
           AS distance,
           b.mydst
      FROM Cities
      JOIN (
        SELECT :LAT AS mylat,
               :LONG AS mylng,
               :RADIUS_LIMIT AS mydst
          FROM DUAL
      )b ON (1 = 1)
     WHERE LATITUDE >=  mylat -(mydst/69)
       AND LATITUDE <=  mylat +(mydst/69)
       AND LONGITUDE >= mylng -(mydst/(69 * COS(RADIANS(mylat))))
       AND LONGITUDE <= mylng +(mydst/(69 * COS(RADIANS(mylat))))
  )a
   WHERE distance <= mydst
   ORDER BY distance

如果您以公里为单位,请将 mydst/69 更改为 mydst/111.045,并将 3959 更改为 6371.4。 (1/69 将英里转换为度;3959 是行星半径的值。)

现在,您可能很想将这个大查询用作“魔法黑匣子”。不要这样做!这不是很难理解,如果你理解它,你将能够做得更好。这是正在发生的事情。

该子句是使查询快速的核心。它会在您的 Cities 表中搜索您指定的附近城市。
     WHERE LATITUDE >=  mylat -(mydst/69)
       AND LATITUDE <=  mylat +(mydst/69)
       AND LONGITUDE >= mylng -(mydst/(69 * COS(RADIANS(mylat))))
       AND LONGITUDE <= mylng +(mydst/(69 * COS(RADIANS(mylat))))

要使其正常工作,您肯定需要在 LATITUDE 列上建立索引。 LONGITUDE 列上的索引也会有所帮助。它会进行近似搜索,查找位于您的点附近地球表面上准矩形斑 block 内的行。它选择了太多的城市,但不是太多。

此处的此子句可让您从结果集中消除额外的城市:
   WHERE distance <= mydst

该子句是计算每个城市与您的点之间的大圆距离的haversine 公式。
           (3959 * ACOS(COS(RADIANS(LATITUDE)) 
                 * COS(RADIANS(mylat)) 
                 * COS(RADIANS(LONGITUDE) - RADIANS(mylng)) 
                 + SIN(RADIANS(LATITUDE)) 
                 * SIN(RADIANS(mylat)) 

此子句允许您输入点和半径限制,作为查询的绑定(bind)变量一次。这很有帮助,因为各种公式多次使用这些变量。
        SELECT :LAT AS mylat,
               :LONG AS mylng,
               :RADIUS_LIMIT AS mydst
          FROM DUAL

查询的其余部分只是简单地组织事物,以便您按距离进行选择和排序。

这里有一个更完整的解释:http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/

关于距离内的 Oracle 空间搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9061770/

相关文章:

linux - 如何在 linux 'screen' 中搜索任何单词

google-bigquery - BigQuery 中的 HAVERSINE 距离?

oracle - 在删除语句中使用 rowid

ruby-on-rails - 为 Rails 中的一个 TestCase 切换 DB-Connection

.net - 组织搜索服务的最佳方式,可以根据过滤器集在大数据库中查找数据

android - Android 应用程序中的反向地理编码

javascript - 将圆的半径(以米为单位)缩放到 D3.js d3.geo.mercator map

java - SQL 条件语句

java - 如何在运行时以编程方式更改默认服务器 Play + Ebean

css - Sproutcore - Webkit 出现在搜索字段中