2012-04-05 41 views

Trả lời

20

Mô-đun này là tùy chọn và không được cài đặt trong mặc định PostgreSQL instalatlion. Bạn phải cài đặt nó từ thư mục contrib.

Bạn có thể sử dụng chức năng sau đây để tính toán khoảng cách tương đối giữa các tọa độ (trong dặm):

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

Bạn có thể giải thích toán học tại đây không? Những gì 69.1 và 57.3 đại diện? – jamesfzhang

+1

Tôi muốn tưởng tượng họ là hằng số sử dụng để chuyển đổi vĩ độ và kinh độ vào dặm. –

+4

Để sử dụng KM thay vì dặm, sử dụng hằng 111,12 & 92,215 thay 69.1 & 57.3 –

5

Giả sử bạn đã cài đặt các module earthdistance một cách chính xác, điều này sẽ cung cấp cho bạn khoảng cách trong dặm giữa hai thành phố . Phương pháp này sử dụng khoảng cách trái đất dựa trên điểm đơn giản hơn. Lưu ý rằng đối số cho điểm() là kinh độ đầu tiên, sau đó là vĩ độ.

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

Cảm ơn, câu trả lời này là cách tốt nhất để làm điều đó. Bạn chỉ cần chạy 'CREATE EXTENSION cube; TẠO TĂNG TRƯỞNG MỞ RỘNG, 'để cài đặt tính bền vững. – sudo

21

Dưới đây là một ví dụ khác sử dụng toán tử điểm:

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

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

Lưu ý rằng points được tạo ra với LONGITUDE FIRST. Theo documentation:

điểm được thực hiện như (kinh độ, vĩ độ) và không phải ngược lại vì kinh độ là gần gũi hơn với ý tưởng trực giác của trục x và vĩ độ để trục y.

Thiết kế khủng khiếp ... nhưng đó là cách thực hiện.

+0

Có một phiếu bầu cho sạch hơn so với câu trả lời khác dựa trên 'earthdistance' – igorsantos07

+0

cảm ơn bạn, giải pháp tuyệt vời! – Bagdat

3

Một phiên bản chính xác hơn về câu trả lời @ strkol, sử dụng giao 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; 

Input là trong độ (ví dụ 52,34273489, 6,23847) và đầu ra là tính bằng mét.

Các vấn đề liên quan