距离内的Oracle空间搜索

ka_*_*lin 4 oracle search geo oracle-spatial

我有下表城市:

ID(int),City(char),latitude(float),longitude(float).
Run Code Online (Sandbox Code Playgroud)

现在根据用户的经度(例如: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';
Run Code Online (Sandbox Code Playgroud)

任何帮助,将不胜感激.

PS:如果可以有距离并进行分类

PPS:我想这样做,这样由于性能问题,我已经以这种方式做到了这一点http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL但它的时间太长...

O. *_*nes 16

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

如果您以公里为单位工作,请将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))))
Run Code Online (Sandbox Code Playgroud)

要使它工作,你肯定需要一个LATITUDE列的索引.LONGITUDE列上的索引也会有所帮助.它进行近似搜索,寻找在您的点附近的地球表面上的准矩形块内的​​行.它选择了太多的城市,但不是太多.

此子句允许您从结果集中删除额外的城市:

   WHERE distance <= mydst
Run Code Online (Sandbox Code Playgroud)

该子句是用于计算每个城市与您的观点之间的大圆距离的半正公式.

           (3959 * ACOS(COS(RADIANS(LATITUDE)) 
                 * COS(RADIANS(mylat)) 
                 * COS(RADIANS(LONGITUDE) - RADIANS(mylng)) 
                 + SIN(RADIANS(LATITUDE)) 
                 * SIN(RADIANS(mylat)) 
Run Code Online (Sandbox Code Playgroud)

此子句允许您输入您的点和半径限制,只需输入一次作为查询的绑定变量.它很有用,因为各种公式多次使用这些变量.

        SELECT :LAT AS mylat,
               :LONG AS mylng,
               :RADIUS_LIMIT AS mydst
          FROM DUAL
Run Code Online (Sandbox Code Playgroud)

查询的其余部分只是组织事物,以便您按距离选择和排序.

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

  • 它有一些神奇的R树索引,它们与普通(B树)索引明显不同,旨在明确解决沿两个维度的接近问题. (3认同)