我正在尝试将表 1(10k 条记录)中的每条记录与其在表中最近的邻居(20k 条记录)连接起来。我希望有一个解决方案不需要我遍历表 1 并为每条记录执行 KNN。
我尝试通过合理的距离限制 KNN 索引,并从表 1 中选择不同的 ID 作为子查询,但这需要我按 ID 号而不是距离进行排序。
非常感谢任何建议。
select distinct on (t1id) t1id, it2d, dist, name, street
from (
select t1id, it2d, dist, name, street
from (
select t1id, it2d, st_distance(t1geom, t2geom) as dist, name, street
from (
select t1.id as t1id,t1.geom as t1geom, t2.id as t2id, t2.geom as t2geom, t1.name, t2.street
from t1
join t2
on st_dwithin(t1.geom, t2.geom, 300)
where t1.seg is null
) as near
order by t1geom <-> t2geom
) as distOrdered
order by dist
) as idOrdered
order by t1id
最佳答案
我找到了一个方法,貌似可以,但是有点丑。我查询第一个查询的结果以获取 ID 号和最短距离,然后将其连接回原始查询以获取每条记录的最短距离。
这远非理想,但我相信会返回正确的结果。
select t1id, it2d, dist, name, street
from (
select t1id, it2d, dist, name, street
from (
select t1id, it2d, dist, name, street
from (
select t1id, it2d, st_distance(t1geom, t2geom) as dist, name, street
from (
select t1.id as t1id,t1.geom as t1geom, t2.id as t2id, t2.geom as t2geom, t1.name, t2.street
from t1
join t2
on st_dwithin(t1.geom, t2.geom, 300)
where t1.seg is null
) as near
order by t1geom <-> t2geom
) as distOrdered
order by dist
) as idOrdered
) as allD
join (
select distinct on (t1id) t1id, min(dist) as md
from (
select t1id, it2d, dist, name, street
from (
select t1id, it2d, st_distance(t1geom, t2geom) as dist, name, street
from (
select t1.id as t1id,t1.geom as t1geom, t2.id as t2id, t2.geom as t2geom, t1.name, t2.street
from t1
join t2
on st_dwithin(t1.geom, t2.geom, 300)
where t1.seg is null
) as near
order by t1geom <-> t2geom
) as distOrdered
order by dist
) as idOrdered
group by t1id order by t1id
) as short
on allD.t1id = short.t1id and allD.dist = short.md
实际上有一种更简单的方法可以通过使用 cross join lateral
来有效地对每一行进行最近邻搜索。
select
t1.id, t1.id, dist
from t1
cross join lateral
(
select st_distance(t1.geom, t2.geom) dist, t2.id
from t2
where t1.seg is null
order by t1.geom <-> t2.geom
limit 1
) as b
where b.dist < 300
关于postgresql - 在大表中使用 PostGIS 为每个点查找最近的邻居 Linstring,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28888933/