如何使用Postgres扩展在半径中搜索?

时间:2017-04-26 10:46:12

标签: sql postgresql

寻找地球表面的距离意味着使用Great Circle距离,使用Haversine公式计算,也称为球面余弦定律公式。

问题在于:给出一张纬度和经度的位置表,哪些位置最接近给定位置?

我有以下查询:

 SELECT z.id,
        z.latitude, z.longitude,
        p.radius,
        p.distance_unit
                    * DEGREES(ACOS(COS(RADIANS(p.latpoint))
                    * COS(RADIANS(z.latitude))
                    * COS(RADIANS(p.longpoint - z.longitude))
                    + SIN(RADIANS(p.latpoint))
                    * SIN(RADIANS(z.latitude)))) AS distance
 FROM doorbots as z
 JOIN (   /* these are the query parameters */
    SELECT 34.0480698 AS latpoint, -118.3589196 AS longpoint,
           2 AS radius,  111.045 AS distance_unit
      ) AS p ON 1=1
 WHERE z.latitude between ... and 
       z.longitude between ...

如何使用earthdistance扩展名来更改查询中复杂的公式?

它是等同的变化吗?

SELECT z.id,
       z.latitude, z.longitude,
       p.radius,
       round(earth_distance(ll_to_earth(p.latpoint, p.longpoint), ll_to_earth(z.latitude, z.longitude))::NUMERIC,0) AS distance
 FROM doorbots as z
 JOIN (   /* these are the query parameters */
    SELECT 34.0480698 AS latpoint, -118.3589196 AS longpoint,
           2 AS radius,  111.045 AS distance_unit
      ) AS p ON 1=1
 WHERE z.latitude between ... and 
       z.longitude between ...

1 个答案:

答案 0 :(得分:1)

您可以通过以下查询充分利用$group

地点足够接近(即在1000000.0米范围内 - 621.371192英里)至(34.0480698,-118.3589196)

earthdistance

最接近(34.0480698,-118.3589196)的前5个地点

select *
from   doorbots z
where  earth_distance(ll_to_earth(z.latitude, z.longitude), ll_to_earth(34.0480698, -118.3589196)) < 1000000.0; -- in meters

select *
from   doorbots z
where  point(z.longitude, z.latitude) <@> point(-118.3589196, 34.0480698) < 621.371192; -- in miles

要使用索引,请将以下内容应用于表格:

select   *
from     doorbots z
order by earth_distance(ll_to_earth(z.latitude, z.longitude), ll_to_earth(34.0480698, -118.3589196))
limit    5;

select   *
from     doorbots z
order by point(z.longitude, z.latitude) <@> point(-118.3589196, 34.0480698)
limit    5;

使用索引:位置足够接近(即在1000000.0米范围内 - 621.371192英里)到(34.0480698,-118.3589196)

create index idx_doorbots_latlong
  on doorbots using gist (earth_box(ll_to_earth(latitude, longitude), 0));

使用指数:最接近(34.0480698,-118.3589196)的前5个地点

with p as (
  select 34.0480698   as latitude,
         -118.3589196 as longitude,
         1000000.0    as max_distance_in_meters
)
select z.*
from   p, doorbots z
where  earth_box(ll_to_earth(z.latitude, z.longitude), 0) <@ earth_box(ll_to_earth(p.latitude, p.longitude), p.max_distance_in_meters)
and    earth_distance(ll_to_earth(z.latitude, z.longitude), ll_to_earth(p.latitude, p.longitude)) < p.max_distance_in_meters;

http://rextester.com/WQAY4056