2017-04-26 6 views
0

地球の表面上の距離を求めることは、Haversine公式(Spherical Cosine Law formula)とも呼ばれる大円距離を使用することを意味します。Postgres拡張機能を使って半径を検索するには?

問題は次のとおりです。緯度と経度のある場所のテーブルが与えられていますが、それらの位置のうちのどれが特定の場所に最も近いのでしょうか?

私は、次のクエリがあります:クエリで私の複雑な数式を変更するearthdistance拡張子を使用する方法

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 ... 

を?

同等の変更ですか?

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 ... 
+0

'earth_distance(ll_to_earth ll_to_earth(z.latitude、z.longitude)、($ 1、$ 2))<$ 3'または'ポイント(z.longitude、z.latitude)<@>点($ 2、$ 1)<$ 3' - ドキュメントについて「地球の距離」は私には明らかです。あなたは正確に何を理解していないのですか? - いくつかのインデックスを関与させたいでしょうか? – pozs

+0

あなたの更新のために:はい、それは同等の変化のようですが、 'z.latitude between ...とz.longitude between ... 'は半径内を探索しません。むしろ「矩形」内にある(実際には、矩形ではなく、球面のような矩形の領域です)。 – pozs

答えて

0

あなたは次のクエリでearthdistanceを最大限に活用することができます(1000000.0メートル内すなわち - 621.371192マイル)十分に近い

場所(-118.3589196、34.0480698)へ:

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 

トップ5の場所に最も近い(34.0480698、-118.3589196)

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; 

インデックスを使用するには、あなたのテーブルに、次のいずれかを適用するための:

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

使用インデックス:十分に近い場所(すなわち、

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; 

使用インデックスの:トップ5場所(34.0480698、-118.3589196)に最も近い:

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

621.371192マイル)(34.0480698、-118.3589196)に - 1000000.0メートル以内http://rextester.com/WQAY4056

関連する問題