计算有序数组中节点之间的总距离

时间:2017-04-13 13:44:17

标签: sql postgresql gis postgis

我有一个网络表,其中的节点由数组中的整数指定,我在输入数据时已经订购了这些节点。整数对应于位置表中的ID,其中包含空间中点的WKT表示。如何计算从开始到结束的网络距离?

最简单的情况如下

 Network Table
 ---------------
| Nodes         |
 ---------------
| {1,2,3}       |
 ---------------


 Location Table
 ---------------
| ID, Point     |
 ---------------
| 1, (1,0)      |
| 2, (2,0)      |
| 3, (2,1)      |
 ---------------

我想为上面的小案例生成值2。结果应该扩展到复杂的网络。

通过使用ST_distance我可以计算网络中所有单个点之间的距离,但我很难保留数组描述的唯一路径。

2 个答案:

答案 0 :(得分:1)

with network (a) as (values ('{1,2,3}'::int[]))
, location (id, p) as (values (1,'(1,0)'::point),(2,'(2,0)'),(3,'(2,1)'))
select a, sum(dt)
from (
    select
        a,
        abs(p[0] - lag(p[0]) over(partition by a order by id)) +
        abs(p[1] - lag(p[1]) over(partition by a order by id)) as dt
    from
        (
            select a, unnest(a) as id
            from network
        ) network
        inner join
        location using (id)
) s
group by a
;
    a    | sum 
---------+-----
 {1,2,3} |   2

使用Postgis:

with network (a) as (values ('{1,2,3}'::int[]))
, location (id, p) as (values
    (1,st_makepoint(1,0)),(2,st_makepoint(2,0)),(3,st_makepoint(2,1))
)
select a, sum(dt)
from (
    select
        a,
        st_distance(p, lag(p) over(partition by a order by id)) as dt
    from
        (
            select a, unnest(a) as id
            from network
        ) network
        inner join
        location using (id)
) s
group by a
;
    a    | sum 
---------+-----
 {1,2,3} |   2

答案 1 :(得分:1)

对于PostgreSQL的point类型(您似乎),您需要<-> operator

select   network_id, sum(dist)
from     (
  select     n.id network_id, point <-> lag(point) over (partition by n.id order by i) dist
  from       network n
  cross join unnest(nodes) i
  join       location l on l.id = i
) s
group by network_id

或者,如果你真的有几何形状和PostGIS,你也可以使用ST_Distance(尽管<->supported by PostGIS too,因为它是距离算子的一般&#34;形式&#34;):

select   network_id, sum(dist)
from     (
  select     n.id network_id, ST_Distance(point, lag(point) over (partition by n.id order by i)) dist
  from       network n
  cross join unnest(nodes) i
  join       location l on l.id = i
) s
group by network_id

http://rextester.com/ESQA1611