mysql - MySQL 空间连接最近点
问题描述
我环顾四周,发现很多人试图按到设定点的距离来订购一张点表,但我很好奇如何在两点之间的最小距离上有效地连接两张表。就我而言,请考虑表格nodes
和centroids
.
CREATE TABLE nodes (
node_id VARCHAR(255),
pt POINT
);
CREATE TABLE centroids (
centroid_id MEDIUMINT UNSIGNED,
temperature FLOAT,
pt POINT
);
我有大约 300k 个节点和 15k 个质心,我想获得离每个节点最近的质心,这样我就可以为每个节点分配一个温度。到目前为止,我已经pt
在两个表上创建了空间索引并尝试运行以下查询:
SELECT
nodes.node_id,
MIN(ST_DISTANCE(nodes.pt, centroids.pt))
FROM nodes
INNER JOIN centroids
ON ST_DISTANCE(nodes.pt, centroids.pt) <= 4810
GROUP BY
nodes.node_id
LIMIT 10;
显然,这个查询不会解决我的问题;它不检索温度,假设最近的质心在 4810 以内,并且只评估 10 个节点。但是,即使进行了这些简化,此查询的优化也很差,并且在我键入时仍在运行。当我让 MySQL 提供有关查询的详细信息时,它说没有使用索引,并且没有任何空间索引被列为可能的键。
我如何构建一个查询,该查询实际上可以使用空间索引有效地返回我想要加入的数据?
解决方案
有很多方法可以解决这个每组最少 n 个问题。
一种方法使用自左连接反模式(这允许联系):
select
n.node_id,
c.centroid_id,
st_distance(n.pt, c.pt) dist,
c.temperature
from nodes n
cross join centroids c
left join centroids c1
on c1.centroid_id <> c.centroid_id
and st_distance(n.pt, c1.pt) < st_distance(n.pt, c.pt)
where c1.centroid_id is null
相同的逻辑可以用not exists
条件来表示。
另一种选择是使用相关子查询进行过滤(这不允许联系):
select
n.node_id,
n.node_id,
c.centroid_id,
st_distance(n.pt, c.pt) dist,
c.temperature
from nodes n
inner join centroids c
on c.centroid_id = (
select c1.centroid_id
from centroids c1
order by st_distance(n.pt, c1.pt)
limit 1
)
最后:如果你想要的只是temperature
最近的质心,那么一个简单的子查询应该是一个不错的选择:
select
n.node_id,
(
select c1.temperature
from centroids c1
order by st_distance(n.pt, c1.pt)
limit 1
) temperature
from nodes n
推荐阅读
- ios - 在 iOS 应用程序中使用 Twitter 登录
- ajax - 如何使用 django 和 ajax 进行星级评分?
- android - 颤振中的 MissingPluginException
- matlab - Matlab中的fmincon输入参数太多
- python-3.x - Using list comprehension with iloc, isna(), sum() and if statement
- firebase - Firebase 身份验证服务
- angular - 在 Angular / Typescript 的 *ngFor 中添加 if else 子句
- javascript - 如何使用javascript将jsonresult绑定到mvc中的标签文本
- java - 用Eclipse在java文件中找到刚刚写的代码(即高亮新部分的代码)
- r - 按年份将数据框转换为存在缺席(包括缺失年份)