使用 MySQL 从点表中查找最近的点

Posted

技术标签:

【中文标题】使用 MySQL 从点表中查找最近的点【英文标题】:Find nearest points with MySQL from points Table 【发布时间】:2016-07-01 19:32:12 【问题描述】:

我有一个像这样的DB Schema(来自this tutorial by Google)-

所以他们在图中的实际点是这样的-

我想要的是找到给定点附近的点(按point_id)按距离排序的点

(x,y) 在 DB 中的位置是 (point_x,point_y)

我想用mysql 解决它,因为我的数据库已经在 MySQL 中了。


更新-

2点的距离就是这么简单-

我想用 MySQL 对距离进行排序。


重新-

为了消除混乱,稍后我想要圆圈内的点。但现在我只想找到排序后的点。

所以你可以忽略圆圈。


我不知道怎么做,有人可以帮忙吗?

【问题讨论】:

你如何定义nearest points 查找两点之间的距离是一个常见问题,在更新问题中给出 我没有要求。你标记了一个圆圈。可能您希望所有这些点都在圆圈内。这就是为什么我问你获得这些分数的标准是什么? 是的,稍后我想要圆内的点。但现在我只想找到排序后的点 问题已更新,供您参考。 【参考方案1】:

我找到了比@1000111 的解决方案更好的解决方案。

在 MySQL 中为此类数据提供了自定义 DB 类型,可提供更好的性能。

OpenGIS in MySQL 非常适合。

函数被赋予here

this *** question 中给出了说明性定义。

我的解决方案是这样的-

数据库表-

CREATE TABLE geoTable
(
    id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(30) NOT NULL,
    geoPoint POINT NOT NULL,
    SPATIAL INDEX(geoPoint)
) ENGINE=MyISAM;


INSERT INTO geoTable (name, geoPoint)
VALUES
  ( "A", GeomFromText('POINT(0.1 -1.01)') ),
  ( "B", ST_GeomFromText('POINT(56.31 2.81)') ),
  ( "C", ST_GeomFromText('POINT(11.1 1.176)') ),
  ( "ui", ST_GeomFromText('POINT(9.1 2.1)') );

SQL 查询-

SELECT
  id,
  name,
  X(geoPoint) AS "latitude",
  Y(geoPoint) AS "longitude",
  (
    GLength(
      LineStringFromWKB(
        LineString(
          geoPoint, 
          GeomFromText('POINT(51.5177 -0.0968)')
        )
      )
    )
  )
  AS distance
FROM geoTable
  ORDER BY distance ASC;

给出了一个示例 SQL Fiddle here。

查看执行时间-

对于 150 条记录,只有 13ms。

【讨论】:

为什么是 LineStringFromWKB ?没有它,查询运行良好,结果完全相同 如果你的表很大,你可以在排序前使用MBRContains函数过滤它,因为这可以利用空间索引。 LineStringFromWKB 为什么要使用它?你能解释一下吗? 高维怎么样? ST_Distance( geoPoint , 'POINT(51.5177 -0.0968)' ) OR ST_Distance_Sphere( geoPoint , 'POINT(51.5177 -0.0968)' )【参考方案2】:

请尝试此查询[直接方法]:

假设,你想找到最接近point_id = 5的点的20个点

SET @givent_point_id := 5;

SELECT 
P1.point_id,
P1.point_name,
P1.point_x,
P1.point_y,
(POW(ABS((P2.point_x - P1.point_x)),2) + POW(ABS((P2.point_y - P1.point_y)),2)) AS sqr_distance
FROM Point P1,
    (SELECT point_x,point_y FROM Point WHERE point_id = @givent_point_id) P2
WHERE P1.point_id <> @givent_point_id
ORDER BY sqr_distance
LIMIT 20;

Demo Here

更多:你可以看看MySQL SPATIAL DATATYPE

MySQL 空间索引使用R-tree 作为专为空间访问方法设计的数据结构。

R-trees 是用于空间访问方法的树数据结构, 即,用于索引多维信息,例如地理 坐标、矩形或多边形。

【讨论】:

很抱歉,我不能使用这种直截了当的方式。因为它太慢了,如果总分> 10000,那么我们不能期待这个查询的答案 因为是服务器,所以可能1秒内有1000个请求进来,可能有100000个点。所以这个过程会失败 不,它是数据库伙伴,所以我们必须应用一些算法以有效的方式找到结果,而不是这样 您是否运行过此查询?执行时间是多少?您可以分享此查询的Explain ... 结果。 @AbrarJahin 现在只有4分,无法比较。可以比较你是否有10000 points 或更多。 NP,让我试试是否有其他选择,如果没有,我应该接受你的回答。感谢您的帮助

以上是关于使用 MySQL 从点表中查找最近的点的主要内容,如果未能解决你的问题,请参考以下文章

使用 MySQL 查找距离内的点

MySQL按顺序查找每组最近/最大的记录

在向量中查找最近的点

PLC的点表(寄存器地址和点表定义)破解探测方案--方便工业互联网数据采集

在数组中查找不等于给定点的最近点

MYSQL 巨大的记录并找到每个最近的点