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

我试图理解我为PostgreSQL/PostGIS编写的一个查询,postgresql,gis,postgis,Postgresql,Gis,Postgis,我创建了一个表,其中包含美国所有邮政编码的列表。我试图查询此表,以获取给定邮政编码特定半径内的所有邮政编码的列表。我正在使用PostgreSQL 9.3和PostGIS扩展 桌子 geom列的创建: 询问 好的,很好,它给了我这个地区的邮政编码,所以我知道我走对了方向。然而,这到底是什么?一开始我用10英里,认为10英里是对的,但我一直在阿拉斯加得到邮政编码59801在蒙大拿州,所以我知道10是不对的。我试图理解的是如何以英里为单位指定距离 我搜索过谷歌,并尝试了一些在搜索中找到的查询,但我尝试

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

桌子 geom列的创建: 询问 好的,很好,它给了我这个地区的邮政编码,所以我知道我走对了方向。然而,这到底是什么?一开始我用10英里,认为10英里是对的,但我一直在阿拉斯加得到邮政编码59801在蒙大拿州,所以我知道10是不对的。我试图理解的是如何以英里为单位指定距离


我搜索过谷歌,并尝试了一些在搜索中找到的查询,但我尝试过的所有查询都不起作用,大多数查询都给了我阿拉斯加的邮政编码。我开始认为我可能是错误地创建了geom专栏。我更感兴趣的是理解我编写的查询,而不是让别人编写一个适合我的查询。如果有人能为我照明,我将不胜感激。

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

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

对于以米为单位的地理单位,测量默认为使用_spheroid=true在WGS 84球体周围测量,为了更快地检查,请使用_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米为半径的邮政编码列表,即59801的10英里范围内的邮政编码列表。正是我想要的。

几何空间参考系统定义的单位基本上意味着度数或米,这取决于地理位置还是投影位置。使用geom::geography作为填充步骤,因为它是直接的,并且还可以转换其他几何体类型。此外,惯例是将此列命名为geog,但正如您所做的那样,将列命名为与其类型相同并没有什么错。
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;
-- 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);