这是我的CSV格式的PostgreSQL示例。
row,latitude,longitude
1,42.082513,-72.621498
2,42.058588,-72.633386
3,42.061118,-72.631541
4,42.06035,-72.634145
我在全世界范围内拥有数千个像这些跨越坐标的行。
我想仅查询表中某个半径范围内的坐标。如何使用PostGIS和PostgreSQL执行此操作?
答案 0 :(得分:9)
您希望"坐标半径5英里范围内的所有行" ,因此不恰好是K-nearest-neighbour (KNN) problem。相关,但你的情况更简单。 "找到离我坐标最近的10行" 将是一个KNN问题。
将坐标转换为geography
值:
ST_SetSRID(ST_MakePoint(longitude, latitude),4326)::geography
或者,您可以使用更简单的geometry
类型。试想一下:
4.2.2. When to use Geography Data type over Geometry data type
然后我们有一个像这样的表:
CREATE TABLE tbl (
tbl_id serial PRIMARY KEY
, geog geography NOT NULL
);
您需要的只是ST_DWithin()
- 和空间索引,以加快速度:
CREATE INDEX tbl_geog_gist ON tbl USING gist(geog);
查询:
SELECT *, ST_Distance(c.x, geog) AS distance -- distance is optional
FROM tbl t, (SELECT ST_GeographyFromText('SRID=4326;POINT(-72.63 42.06)')) AS c(x)
WHERE ST_DWithin(c.x, geog, 8045) -- distance in meter
ORDER BY distance; -- order is optional, you did not ask for that
或您可以使用原始列并创建功能索引... 关于dba.SE这个密切相关的答案中的这个和其他细节:
答案 1 :(得分:3)
您应首先使用COPY
command(如果文件可供PostgreSQL 服务器访问)或\copy
command Reverse Geocoding in Python Geocoder从CSV格式的文件创建表格。 1}}如果文件不是服务器的本地文件。如果您遇到任何问题,请参阅SO上的其他Q + A.
在表格中显示数据后,您应将psql
和longitude
列转换为PostGIS latitude
类型,方法是在{{1}类型的表格中添加一列然后使用适当的值填充该列(此处称为geography
):
geography(POINT, 4326)
在该列上添加索引以便进行有效搜索:
gps
现在,您可以找到距离指定位置5英里范围内的行,例如UPDATE my_table SET gps = ST_SetSRID(ST_MakePoint(longitude, latitude), 4326);
,如下:
CREATE INDEX my_table_gps ON my_table USING gist(gps);
请注意,(-72.657, 42.0657)
列上的SELECT *
FROM my_table
WHERE ST_DWithin(gps, ST_SetSRID(ST_MakePoint(-72.657, 42.0657), 4326), 5 * 1609);
将以米为单位,因此您必须将英里半径乘以一英里的1,609米。