从指定坐标获取 5 英里范围内的所有建筑物

Getting all Buildings in range of 5 miles from specified coordinates

我的数据库 table Building 包含以下列:namelatlng

如何获取距指定坐标 5 英里范围内的所有 Buildings,例如这些:

-84.38653999999998

33.72024

我试过了,但没有用:

SELECT ST_CONTAINS(
  SELECT ST_BUFFER(ST_Point(-84.38653999999998,33.72024), 5), 
  SELECT ST_POINT(lat,lng) FROM "my_db"."Building" LIMIT 50
);

https://docs.aws.amazon.com/athena/latest/ug/geospatial-functions-list.html

为什么要将 x,y 存储在不同的列中?我强烈建议您将它们存储为 geometrygeography 以避免查询时不必要的转换开销。

也就是说,您可以使用 ST_DWithinST_Distance:

计算和检查以英里为单位的距离

(测试数据)

CREATE TABLE building (name text, long numeric, lat numeric);
INSERT INTO building VALUES ('Kirk Michael',-4.5896,54.2835);
INSERT INTO building VALUES ('Baldrine',-4.4077,54.2011);
INSERT INTO building VALUES ('Isle of Man Airport',-4.6283,54.0804);

ST_DWithin

ST_DWithin return 如果给定的几何形状与另一个几何形状在指定的距离内,则为真。以下查询搜索距 POINT(-4.6314 54.0887):

5 英里半径范围内的几何图形
SELECT name,long,lat,
  ST_Distance('POINT(-4.6314 54.0887)'::geography,
              ST_MakePoint(long,lat)) * 0.000621371 AS distance
FROM building
WHERE
  ST_DWithin('POINT(-4.6314 54.0887)'::geography,
              ST_MakePoint(long,lat),8046.72); -- 8046.72 metres = 5 miles;

        name         |  long   |   lat   |     distance      
---------------------+---------+---------+-------------------
 Isle of Man Airport | -4.6283 | 54.0804 | 0.587728347062174
(1 row)

ST_Distance

函数 ST_Distance(使用 geography 类型参数)将 return 距离 。使用这个功能你所要做的就是最后把米换算成英里。

注意:使用ST_Distance的查询中的距离是实时计算的,因此不要使用空间索引。所以,不建议在WHERE子句中使用该函数!在 SELECT 子句中使用它。尽管如此,下面的示例显示了如何完成:

SELECT name,long,lat,
  ST_Distance('POINT(-4.6314 54.0887)'::geography,
              ST_MakePoint(long,lat)) * 0.000621371 AS distance
FROM building
WHERE 
  ST_Distance('POINT(-4.6314 54.0887)'::geography,
              ST_MakePoint(long,lat)) * 0.000621371 <= 5;

        name         |  long   |   lat   |     distance      
---------------------+---------+---------+-------------------
 Isle of Man Airport | -4.6283 | 54.0804 | 0.587728347062174
(1 row)
  • 注意参数顺序ST_MakePoint:是经度,纬度..不是相反。

演示:db<>fiddle

Amazon Athena 等效项(以度为单位的距离):

SELECT *, ST_DISTANCE(ST_GEOMETRY_FROM_TEXT('POINT(-84.386330 33.753746)'),
      ST_POINT(long,lat)) AS distance
FROM building
WHERE 
  ST_Distance(ST_GEOMETRY_FROM_TEXT('POINT(-84.386330 33.753746)'),
  ST_POINT(long,lat)) <= 5;

第一件事。如果可能,请使用 Postgis 而不是 amazon-athena。看文档 athena 看起来像是一个空间工具的阉割版。

首先 - 安装 postgis。

 CREATE EXTENSION postgis SCHEMA public;

现在为数据创建几何(如果你想使用像 3857 这样的公制 SRID)或地理(如果你想使用像 4326 这样的度数 SRID)列。

alter table building add column geog geography;

然后将您的点数据 (lat,long) 数据转换为 geometry/geography:

update building
   set geog=(ST_SetSRID(ST_MakePoint(lat,long),4326)::geography)

接下来在其上创建空间索引

create index on buildings using gist(geog);

现在您可以开始行动了

select *, 
       st_distance(geog, ST_makePoint(-84.386,33.72024))/1609.34 dist_miles
  from building
 where st_dwithin(geog, ST_makePoint(-84.38653999999998,33.72024),5*1609.34);

几句解释: 如果您的 table 中有很多记录,索引很有用。 ST_Dwithin 在 st_distance 不使用索引时使用索引,因此 ST_dwithin 将使您在大数据集上的查询速度更快。