微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

sql – 两个坐标之间的距离,我该如何简化和/或使用不同的技术?

我需要编写一个查询,允许我从提供的位置查找范围内的所有位置(英里).

表格是这样的:

id  |  name  |  lat  |  lng

所以我一直在做研究,发现:this my sql presentation

我已经在一个大约100行的桌子上测试了它,还有更多! – 必须可扩展.

我首先尝试了更简单的事情:

//just some test data this would be required by user input    
set @orig_lat=55.857807; set @orig_lng=-4.242511; set @dist=10;

SELECT *,3956 * 2 * ASIN(
          SQRT( POWER(SIN((orig.lat - abs(dest.lat)) * pi()/180 / 2),2) 
              + COS(orig.lat * pi()/180 ) * COS(abs(dest.lat) * pi()/180)  
              * POWER(SIN((orig.lng - dest.lng) * pi()/180 / 2),2) )) 
          AS distance
  FROM locations dest,locations orig
 WHERE orig.id = '1'
HAVING distance < 1
 ORDER BY distance;

这个返回的行在50ms左右,非常好!
然而,随着行的增加,这将显着减慢.

EXPLAIN显示它只使用显而易见的PRIMARY键.

然后阅读文章linked above.我尝试过这样的事情:

// defining variables - this when made into a stored procedure will call
// the values with a SELECT query.
set @mylon = -4.242511;
set @mylat = 55.857807;
set @dist = 0.5;

-- calculate lon and lat for the rectangle:
set @lon1 = @mylon-@dist/abs(cos(radians(@mylat))*69);
set @lon2 = @mylon+@dist/abs(cos(radians(@mylat))*69);
set @lat1 = @mylat-(@dist/69); 
set @lat2 = @mylat+(@dist/69);

-- run the query:

SELECT *,3956 * 2 * ASIN(
          SQRT( POWER(SIN((@mylat - abs(dest.lat)) * pi()/180 / 2),2)
              + COS(@mylat * pi()/180 ) * COS(abs(dest.lat) * pi()/180)
              * POWER(SIN((@mylon - dest.lng) * pi()/180 / 2),2) ))
          AS distance
  FROM locations dest
 WHERE dest.lng BETWEEN @lon1 AND @lon2
   AND dest.lat BETWEEN @lat1 AND @lat2
HAVING distance < @dist
 ORDER BY distance;

这个查询的时间大约是240ms,这不是太糟糕,但比上一次要慢.但我可以想象,在更高的行数下,这会更快.但是,anEXPLAIN将可能的键显示为lat,lng或PRIMARY并使用PRIMARY.

我怎么能这样做更好???

我知道我可以将lat lng存储为POINT();但是我也没有找到太多关于此的文件,这表明它是否更快或更准确?

任何其他想法都会被愉快地接受!

非常感谢!

-Stefan

更新:

正如Jonathan Leffler所指出的那样,我犯了一些我没有注意到的错误

我只将abs()放在其中一个lat值上.当我没有需要时,我也在第二个WHERE子句中使用id搜索.在第一个查询纯粹是实验性的,第二个查询更有可能达到生产.

在这些更改之后,EXPLAIN显示密钥现在使用lng列,平均时间现在响应180ms左右,这是一个改进.

解决方法

任何其他想法都会被愉快地接受!

如果您想要速度(和简单性),您需要从数据库获得一些不错的地理空间支持.这引入了地理空间数据类型,地理空间索引和(许多)处理/构建/分析地理空间数据的功能.

MysqL implements a part of the OpenGIS specifications虽然它/是(上次我检查过它)非常非常粗糙的边缘/过早(对任何实际工作都没用).

PostGisPostgreSql将使这个简单易读:

(这可以从tableb中找到距离距离表格中的a点1000米的所有点,其中id为123)

select 
    myvalue
from 
    tablea,tableb
where 
    st_dwithin(tablea.the_geom,tableb.the_geom,1000)
and
    tablea.id = 123

原文地址:https://www.jb51.cc/mssql/83434.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐