我有下表城市:
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/