让所有建筑物距离指定坐标5英里

pau*_*aul 2 sql gis postgis presto amazon-athena

我有数据库表Building与这些列:name,lat,lng

如何Buildings在指定坐标的5英里范围内获取全部范围,例如:

-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
);
Run Code Online (Sandbox Code Playgroud)

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

Jim*_*nes 6

为什么要将x,y存储在分隔的列中?我真诚地建议您将它们存储为geometrygeography避免查询时间中的投射开销.

话虽这么说,您可以使用以下内容计算距离(以英里为单位):

(测试数据)

CREATE TEMPORARY TABLE building (name text, lat numeric, long numeric);
INSERT INTO building VALUES ('foo',7.52,51.96);
INSERT INTO building VALUES ('bar',7.62,51.94);
INSERT INTO building VALUES ('far away ... ',10.62,59.94);
Run Code Online (Sandbox Code Playgroud)

该函数ST_Distance(带有geography类型参数)将返回以米为单位的距离.您所要做的就是最后将米转换为英里.就像是:

SELECT *, ST_Distance(ST_GeographyFromText('POINT(7.62 51.93)'),
      ST_MakePoint(lat,long)) * 0.000621371 AS distance
FROM building
WHERE 
  ST_Distance(ST_GeographyFromText('POINT(7.62 51.93)'),
  ST_MakePoint(lat,long)) * 0.000621371 > 5

     name      |  lat  | long  |     distance     
---------------+-------+-------+------------------
 far away ...  | 10.62 | 59.94 | 566.123267141404
(1 Zeile)
Run Code Online (Sandbox Code Playgroud)

编辑 - 相当于亚马逊雅典娜(距离度):

SELECT *, ST_DISTANCE(ST_GEOMETRY_FROM_TEXT('POINT(-84.386330 33.753746)'),
      ST_POINT(lat,long)) AS distance
FROM building
WHERE 
  ST_Distance(ST_GEOMETRY_FROM_TEXT('POINT(-84.386330 33.753746)'),
  ST_POINT(lat,long)) > 5;
Run Code Online (Sandbox Code Playgroud)


Grz*_*bek 5

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

首先 - 安装 postgis。

 CREATE EXTENSION postgis SCHEMA public;
Run Code Online (Sandbox Code Playgroud)

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

alter table building add column geog geography;
Run Code Online (Sandbox Code Playgroud)

然后将您的点数据(经纬度)数据转换为几何/地理:

update building
   set geog=(ST_SetSRID(ST_MakePoint(lat,long),4326)::geography)
Run Code Online (Sandbox Code Playgroud)

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

create index on buildings using gist(geog);
Run Code Online (Sandbox Code Playgroud)

现在您已准备好采取行动

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);
Run Code Online (Sandbox Code Playgroud)

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