【问题标题】:I'm trying to understand a query I've written for PostgreSQL / PostGIS我试图理解我为 PostgreSQL / PostGIS 编写的查询
【发布时间】:2014-10-23 02:31:37
【问题描述】:

我创建了一个表格,其中包含美国所有邮政编码的列表。我正在尝试查询此表以获取给定邮政编码一定半径内的所有邮政编码的列表。我正在使用带有 PostGIS 扩展的 PostgreSQL 9.3。

桌子

CREATE TABLE city
(
  city_id serial NOT NULL,
  region_id integer,
  country_id integer,
  name text NOT NULL,
  postal_code text,
  longitude real,
  latitude real,
  geom geometry(Point,4326),
  CONSTRAINT city_id_pk PRIMARY KEY (city_id)
  WITH (FILLFACTOR=100),
  CONSTRAINT country_id_fk FOREIGN KEY (country_id)
      REFERENCES country (country_id) MATCH FULL
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT region_id_fk FOREIGN KEY (region_id)
      REFERENCES region (region_id) MATCH FULL
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
  OIDS=FALSE
);
ALTER TABLE city
  OWNER TO personnelity092014;


CREATE INDEX idx_city_geom
  ON city
  USING gist
  (geom);

geom Column的创建:

SELECT AddGeometryColumn ('public','city','geom',4326,'POINT',2);

UPDATE city SET geom = ST_PointFromText('POINT(' || longitude || ' ' || latitude || ')', 4326);

查询

SELECT z.postal_code
  FROM city z, city z2
  WHERE z2.postal_code = '59801' 
    AND st_expand(z2.geom, .1) && z.geom   
    AND st_distance(z.geom, z2.geom) <= .1;

好的,太好了,它为我提供了该地区周围的邮政编码,所以我知道我在正确的轨道上。但是,0.1 到底是什么?起初我想用 10 英里(是的,没错),但我一直在阿拉斯加(蒙大拿州是 59801)得到邮政编码,所以我知道 10 是不对的。我想了解的是如何以英里为单位指定距离。

我搜索了 Google 并尝试了一些我在搜索中找到的查询,但我尝试过的查询都没有奏效——其中大多数都给了我阿拉斯加的邮政编码。我开始认为我可能错误地创建了我的 geom 列。我对理解我写的查询比让某人写一个对我“有效”的查询更感兴趣。如果有人可以为我照亮,将不胜感激。

【问题讨论】:

    标签: postgresql gis postgis


    【解决方案1】:

    好的,所以我想通了。如果您遵循 Google 搜索中的大多数指南,您将被引导创建一个几何列(例如,this guide)。但是,在进行半径搜索时,似乎您想要的是地理(除非您拥有 GIS 学位并且实际上知道如何使用 geom 列)。事实上,ST_DWithin 的 PostGIS 文档非常清楚地说明了这一点:

    对于几何:距离以几何的空间参考系统定义的单位指定。要使此函数有意义,源几何图形必须具有相同的坐标投影,具有相同的 SRID。

    对于地理单位以米为单位,测量默认为 use_spheroid=true(围绕 WGS 84 球体测量),为了更快地检查,use_spheroid=false 沿球体测量。

    因此,考虑到这一点,并不完全理解“由几何空间参考系统定义的单位”。我做了以下设置地理专栏:

    -- Create the geography column
    ALTER TABLE city ADD COLUMN geography geography(Point,4326); 
    -- Populate it
    UPDATE city SET geography = ST_GeographyFromText('SRID=4326;POINT(' || st_x(geom) || ' ' ||  st_y(geom) || ')');
    

    好的,现在当我执行以下查询时:

    SELECT z.postal_code
    FROM city z, city z2
    WHERE z2.postal_code = '59801'    
        AND st_dwithin(z.geography, z2.geography, 16093);
    

    我得到了 59801 半径 16093 米或约 10 英里范围内的邮政编码列表。正是我想要的。

    【讨论】:

    • 几何空间参考系统定义的单位基本上是度数或米,具体取决于地理或投影。
    • 使用geom::geography 进行“填充”步骤,因为它是直接的并且也可以转换其他几何类型。此外,惯例是将此列称为geog,但正如您所做的那样,将列命名为与其类型相同并没有错。
    猜你喜欢
    • 1970-01-01
    • 2015-08-08
    • 1970-01-01
    • 1970-01-01
    • 2019-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多