按名次对数据进行排序cpp_【数据库】mysql中如何按距离排序筛选商家

在开发接口的时候也许你会遇到这样的情景:从数据库中筛选商家的时候需要在指定范围内按距离排序,你们是怎么处理的呢?

我看过有的童鞋是这样处理的,在sql里直接计算距离,然后排序,大概是以下的写法:

ACOS( SIN((#{lat} * 3.1415) / 180 ) *SIN((merchant.latitude * 3.1415) / 180 )  + COS((#{lat} * 3.1415) / 180 )  * COS((merchant.latitude * 3.1415) / 180 )  * COS((#{lng}* 3.1415) / 180 - (merchant.longitude * 3.1415) / 180 ) ) * 6380 AS distance

这种写法一看就不妥,在sql中复杂运算是不推荐的。这个需求可以优化下筛选方圆指定范围内的商家然后在内存中进行计算距离排序,无需在数据库中全部计算一遍距离然后排序。如果以用户为中心,筛选方圆一公里范围的商家然后按距离排序,计算出前后1公里范围的经纬度差值,大概如下图

f0543f316b584df045ccc2a9db0ea234.png

简化成这个模型后,黑点地方的数据是不需要的,但是这部分数据可以忽略不计,稍后在内存中计算距离可以去除。我们知道地球可以看成是一个圆球

dbd02de4b3af2a665063ecac7cf48634.png
地球周长是2*6371*3.14 那么1公里对应的经度差值是(1/(2*6371*3.14))*180 大概0.004498, 1公里对应的纬度差值(1/(2*6371*3.14))*90 大概0.002249,所以在sql中筛选between lng-0.004498 and lng+0.004498 纬度同样如此。

不过有人帮我们处理好了这些事情,只需要引入jar包即可

com.spatial4j spatial4j 0.5int radius = 1; //筛选范围 公里//lon, lat用户当前的经纬度SpatialContext geo = SpatialContext.GEO;Rectangle rectangle = geo.getDistCalc().calcBoxByDistFromPt( geo.makePoint(lon, lat), radius * DistanceUtils.KM_TO_DEG, geo, null);rectangle.getMinX() getMaxX() getMinY() getMaxY()既是表示方圆1公里内的经纬度。这样数据中的筛选条件就可以优化下了
7ad34f2e22a32be1bd6695a3acdc3bd3.png

这样效率就能提高了很多,筛选出数据之后,还需要计算具体的距离然后排序,计算距离如下

SpatialContext geo = SpatialContext.GEO;double distance = geo.calcDistance(geo.makePoint(lon, lat), geo.makePoint(memberLon, memberLat)) * DistanceUtils.DEG_TO_KM;

当然这只是初步优化方案,如果你有更好的方案欢迎在下方留言。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值