我试图理解我为PostgreSQL / PostGIS编写的查询

时间:2014-10-23 02:31:37

标签: postgresql gis postgis

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

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列:

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;

好的,很好,它给了我区域附近的邮政编码,所以我知道我在正确的轨道上。但是,到底是什么.1?起初我打算10点,想着10英里(是的),但是我在阿拉斯加(59801在蒙大拿州)一直得到邮政编码,所以我知道10不对。我想要了解的是如何以英里为单位指定距离。

我搜索了Google,并尝试了一些我在搜索中发现的查询,但我尝试过的查询都没有效果 - 大部分都在阿拉斯加给我邮政编码。我开始认为我可能错误地创建了我的geom列。我更感兴趣的是理解我写过的查询,而不是让别人写一个“只是工作”的查询。为了我。如果有人能为我照亮,那就非常感激。

1 个答案:

答案 0 :(得分:0)

好吧,所以我明白了。如果您按照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);

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