在给定距离处查找彼此远离的表格中的坐标
Posted
技术标签:
【中文标题】在给定距离处查找彼此远离的表格中的坐标【英文标题】:Find coordinates in a table away from each other at given distance 【发布时间】:2018-05-29 09:13:20 【问题描述】:mysql 表中有类似的数据。 (大约 500k)条记录
id latitude longitude
------ ---------- ------------
106837 24.7218925 68.2604037
106838 24.7218947 68.260412
106839 24.7219007 68.2604083
106840 24.721902 68.260403
106841 24.7219149 68.260416
106842 24.7219169 68.2604118
106843 24.7219172 68.2604141
106844 24.7219269 68.2604097
106845 24.7219299 68.2604039
106846 24.7219346 68.2603994
106847 24.7219409 68.2604027
106848 24.7219434 68.2604129
106849 24.721956 68.2603941
106850 24.7219879 68.2603614
106851 24.7268579 68.2586257
106852 24.7283047 68.2575022
106853 24.7283047 68.2575032
106854 24.7283141 68.2575256
106855 24.728375 68.2575342
106856 24.7283862 68.2575007
106857 24.7284202 68.2575555
106858 24.7284468 68.257605
106859 24.7284485 68.2576076
106860 24.7284639 68.2576095
106861 24.7284675 68.2576157
我想过滤所有相距 100 米的坐标。
我有 500k 个坐标,其中一些坐标大约取自相同的位置并相互重叠,但我只想区分所有至少相距 100 米的坐标
架构:
CREATE TABLE `coordinates` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`region` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`area` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`territory` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`town` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`latitude` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`longitude` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`completed` tinyint(1) NOT NULL DEFAULT '0',
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=533273 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
用图片和更多细节更新我的问题。
图片更清晰:
如您所见,我在地图 A、B、C、D、E、F 上有 6 个坐标,我的表格中有这些坐标,如下所示。
现在,只检索 A、B、C 和 D 坐标的查询是什么?我不想得到 E 和 F,因为 E 已经离 D 最近,而 F 离 C 很近,或者我们可以说 E、F 都在其他坐标的 100 米半径范围内。希望你能理解我的问题。
【问题讨论】:
你可以通过使用where
子句得到这个,其中差值大于等于100
你在解决这个问题的哪一部分?
如果这些代表地球上的坐标,那么我认为所有点之间的距离都远远超过 100m。
请看现在我已经更新了我的数据,我的桌子上有真实的坐标。
【参考方案1】:
算法1.聚类分析
据我了解,您想找到点的“集群”。这是一个非常困难的数学挑战。它超出了简单 SQL 操作的范围。
算法 2. 详尽
所以我将简化任务。您从 500K 点的列表开始。您将从列表中删除点,直到没有两个点“彼此非常接近”。
Foreach point, A, remaining in the list
Foreach other point, B, in the list
If A and B are within 100 meters, delete B from the list.
让我们分析一下这个简单的算法。
假设最终结果将是 100K 点。我们需要询问您需要执行多少次“is A near B”测试。
第一点 A 必须与 500K-1 Bs 进行比较。 最后一点 A 必须与大约 100K Bs 进行比较。 所以比较的总数在 100K^2 和 500K^2 之间。这些值是 10 billion 和 250 billion 。呸。这可能需要数周才能运行。
算法 3:“桶”
-
制作一个 200 米乘 200 米的网格。 (简单 SQL;50 万次操作)
计算每个点在哪个桶中。将其放在与该点相关的列中。
对于每个桶,进行距离检查以消除“非常接近”的点。 (可能只有几百万次测试。)
现在您即将获得一个已清理的点列表。但是两个接近点可能在网格中的相邻存储桶中。这可以通过重做网格向东移动 100 米,然后向南,然后向西移动来解决。即上述3个步骤共执行4次。
距离
同时,你真的想用VARCHAR(191)
做算术吗?如果你想使用ST_Distance_Sphere()
,你可以这样做。或者您可以切换到DOUBLE
并使用简单的毕达哥拉斯算法。 (我不知道哪个会更快。但我知道任何一个都足够精确,可以决定对抗微小的 100 米。
请使用 InnoDB。
【讨论】:
【参考方案2】:您可以通过使用 ST_Distance_Sphere(g1, g2 [, radius]) mysql 函数的where
子句在差异大于等于 100 的情况下获得此信息
select *
from tbl
where ST_Distance_Sphere(POINT(Latitude,Longitude), POINT(Latitude,Longitude)) >=100
【讨论】:
我认为你没有明白我的意思。我有 500k 坐标,其中一些坐标大约取自相同的位置并相互重叠,但我只想区分所有至少相距 100 米的坐标。 你能确定一下,上面的查询对你有用吗?我有 5.7.19 的 mysql。我还分享了有问题的表架构。 另一个问题 --- SELECT ST_Distance_Sphere(POINT(latitude, longitude), POINT(latitude, longitude)) AS 'distance' --- 它正在工作,但每行返回 0。跨度> 问题是如何将表格中的每个坐标与特定距离进行比较。以上是关于在给定距离处查找彼此远离的表格中的坐标的主要内容,如果未能解决你的问题,请参考以下文章