2012-04-05 2 views

Antwort

20

Dieses Modul ist optional und wird nicht in der standardmäßigen PostgreSQL Instalatlion installiert. Sie müssen es aus dem Verzeichnis contrib installieren.

Sie können die folgende Funktion verwenden, um die ungefähre Entfernung zwischen den Koordinaten (in Meilen) zu berechnen:

CREATE OR REPLACE FUNCTION distance(lat1 FLOAT, lon1 FLOAT, lat2 FLOAT, lon2 FLOAT) RETURNS FLOAT AS $$ 
DECLARE             
    x float = 69.1 * (lat2 - lat1);       
    y float = 69.1 * (lon2 - lon1) * cos(lat1/57.3);   
BEGIN              
    RETURN sqrt(x * x + y * y);        
END 
$$ LANGUAGE plpgsql; 
+2

Können Sie die Mathematik hier erklären? Was repräsentieren 69.1 und 57.3? – jamesfzhang

+1

Ich könnte mir vorstellen, dass es sich um Konstanten handelt, mit denen Längen- und Breitengrade in Meilen umgerechnet werden. –

+4

Um KM statt Meilen zu verwenden, verwenden Sie Konstanten 111.12 & 92.215, um 69.1 & 57.3 zu ersetzen. –

5

Vorausgesetzt, dass Sie das earthdistance Modul korrekt installiert haben, dies wird Ihnen die Entfernung in Meilen zwischen zwei Städten . Diese Methode verwendet die einfacheren punktbasierten Erdabstände. Beachten Sie, dass die Argumente für Punkt() zuerst Längengrad und dann Breitengrad sind.

create table lat_lon (
    city varchar(50) primary key, 
    lat float8 not null, 
    lon float8 not null 
); 

insert into lat_lon values 
('London, GB', 51.67234320, 0.14787970), 
('New York, NY', 40.91524130, -73.7002720); 

select 
    (
    (select point(lon,lat) from lat_lon where city = 'London, GB') <@> 
    (select point(lon,lat) from lat_lon where city = 'New York, NY') 
) as distance_miles 

distance_miles 
-- 
3447.58672105301 
+0

Danke, diese Antwort ist der beste Weg, es zu tun. Sie müssen nur 'CREATE EXTENSION Cube ausführen; CREATE EXTENSION Erddistanz; 'Erddistanz installieren. – sudo

21

Hier ist ein weiteres Beispiel der Punkt-Operator:

create extension cube; 
create extension earthdistance; 
select (point(-0.1277,51.5073) <@> point(-74.006,40.7144)) as distance; 

    distance  
------------------ 
3461.10547602474 
(1 row) 

Beachten Sie, dass points mit LONGITUDE FIRST erstellt werden. Per der documentation:

Punkte werden als (Länge, Breite) aufgenommen und nicht umgekehrt, weil Länge näher an die intuitive Idee der x-Achse und Breitengrad y-Achse ist.

Welches ist schreckliches Design ... aber so ist es.

+0

Haben Sie eine Stimme für sauberer als die andere Antwort basierend auf "Earthdistance" – igorsantos07

+0

danke, tolle Lösung! – Bagdat

3

Eine genauere Version von @ strkol Antwort, wobei den Eingang Haversine formula

CREATE OR REPLACE FUNCTION distance(
    lat1 double precision, 
    lon1 double precision, 
    lat2 double precision, 
    lon2 double precision) 
    RETURNS double precision AS 
$BODY$ 
DECLARE 
    R integer = 6371e3; -- Meters 
    rad double precision = 0.01745329252; 

    φ1 double precision = lat1 * rad; 
    φ2 double precision = lat2 * rad; 
    Δφ double precision = (lat2-lat1) * rad; 
    Δλ double precision = (lon2-lon1) * rad; 

    a double precision = sin(Δφ/2) * sin(Δφ/2) + cos(φ1) * cos(φ2) * sin(Δλ/2) * sin(Δλ/2); 
    c double precision = 2 * atan2(sqrt(a), sqrt(1-a));  
BEGIN              
    RETURN R * c;   
END 
$BODY$ 
    LANGUAGE plpgsql VOLATILE 
    COST 100; 

verwendet, ist in Graden (z.B. 52,34273489, 6,23847) und Ausgang ist in Metern.