postgresql - 在大表中使用 PostGIS 为每个点查找最近的邻居 Linstring

标签 postgresql postgis

我正在尝试将表 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/

相关文章:

postgresql - 如何在 Vapor 3/Fluent 中记录 SQL 语句?

postgresql - 是否可以将 SQL Server CTE 查询转换为 Postgres?

performance - 索引和性能

python - postgresql/postgis 中的响应时间查询比较

php - pg_query 有效但 pg_query_params 无效

sql - PostgreSql 表中 UUID、CHAR 和 VARCHAR 之间的性能差异?

java - 无法将名称 [org.hibernate.spatial.dialect.postgis.PostgisDialect] 解析为策略 [org.hibernate.dialect.Dialect]

sql - 比较几何时查询速度慢

python - Django-tenant-schemas 和 GeoDjango 一起

sql - 如何获得两行之间的时间差?