使用postGIS

时间:2016-12-21 16:47:35

标签: postgresql postgis

我是PostGIS的新手,我想在我的数据库中为一个存储其纬度和经度(2D点)的新地点创建一个列。后来我希望能够找到这两点之间的距离。

似乎我可以通过运行以下查询来完成我想要的任务:

CREATE EXTENSION postgis;

CREATE TABLE places (
    id SERIAL PRIMARY KEY,
    name VARCHAR(500) NOT NULL,
    location geometry NOT NULL
);

INSERT INTO places (name, location)
VALUES ('The Place of Luke', ST_SetSRID(ST_MakePoint(-71.1043443253471, 42.3150676015829),4326)),
('The Place of Bob', ST_SetSRID(ST_MakePoint(-75.1043443253471, 43.3150676015829),4326));

SELECT ST_Distance(
        (SELECT location FROM places WHERE name = 'The Place of Luke'),
        (SELECT location FROM places WHERE name = 'The Place of Bob')
    );

我相信这是正确地返回4.12310562561766纬度和经度的距离,但我有几个关于最佳实践的问题。

  1. {I} geometry是我想要完成的正确类型吗?我尝试将geometry更改为point

    CREATE TABLE places (
        id SERIAL PRIMARY KEY,
        name VARCHAR(500) NOT NULL,
        location point NOT NULL
    );
    
    INSERT INTO places (name, location)
    VALUES ('The Place of Luke', ST_MakePoint(-71.1043443253471, 42.3150676015829)),
    ('The Place of Bob', ST_MakePoint(-75.1043443253471, 43.3150676015829));
    
    SELECT ST_Distance(
        (SELECT location FROM places WHERE name = 'The Place of Luke'),
        (SELECT location FROM places WHERE name = 'The Place of Bob')
    );
    

    但我一直得到ERROR: column "location" is of type point but expression is of type geometry。我知道ST_MakePoint可能正在尝试创建geometry类型的东西并导致错误,但是如何创建类型为point的东西呢?

  2. documentation似乎非常坚持我应该使用AddGeometryColumn()而不是将列直接添加到我的位置表中,但我不明白为什么以及这是否会成为问题我的申请增长了。如果我需要做的就是找到两个地方(在2D平面上)之间的距离,以便陆路旅行,这对我来说是个问题吗?
  3. 如何将此结果转换为里程(可能是公里数)。我应该一起运行不同的查询吗?我对经度和纬度的理解使我认为返回的这个数字不会是简单的线性转换为里程数。

2 个答案:

答案 0 :(得分:2)

  1. 是的,如果您使用的是PostGIS,请不要使用point。 Point是本机类型。 PostGIS是一个可以满足您需求的扩展。如果一切都在4326中,您应该查看geography类型并使用它。
  2. 除非您使用的是PostGIS 1.x,否则请勿使用AddGeometryColumn()。 PostGIS 2.x支持类型修饰符,您可以使用ALTER TABLE代替。
  3. 要使用里程,只需返回km和* 0.621371192
  4. 这有点奇怪,但功能齐全。

    SELECT ST_Distance(
        (SELECT location FROM places WHERE name = 'The Place of Luke'),
        (SELECT location FROM places WHERE name = 'The Place of Bob')
    );
    

    通常情况下,您在JOIN中看到这个批处理工作,但它也可以在相关的子查询中工作。

    SELECT
      l1.location,
      l2.location,
      ST_Distance( l1.location, l2.location )
    FROM location AS l1
    JOIN location AS l2
      ON l2.location = 'The Place of Luke'
    WHERE places = 'The Place of Bob';
    

答案 1 :(得分:1)

我建议使用

  • 使用geography(Point,4326)作为位置
  • 的数据类型
  • 查询为ST_Distance(location1::geography, location2::geography)

通过转换为geography数据类型,结果为meters,而不是度,这将毫无意义。请注意,4326与WGS84(大多数GPS数据引用的内容)是相同的系统

有关详细信息,请参阅此Q / A:

https://gis.stackexchange.com/questions/76967/what-is-the-unit-used-in-st-distance

编辑:

re:AddGeometryColumn不需要使用该功能,只是方便 - 据我所知。

编辑:

另外一个注释,不是你问的问题,但postgis中还有空间索引类型:

CREATE INDEX loc_idx ON places USING gist (location);