Tôi nghĩ câu hỏi của bạn cho biết bạn có city
giá trị cho hai thành phố mà bạn muốn tính khoảng cách.
Truy vấn này sẽ thực hiện công việc cho bạn, cho biết khoảng cách tính bằng km. Nó sử dụng công thức định luật cosin hình cầu.
Lưu ý rằng bạn nối bảng với chính nó để bạn có thể truy xuất hai cặp tọa độ để tính toán.
SELECT a.city AS from_city, b.city AS to_city,
111.111 *
DEGREES(ACOS(LEAST(1.0, COS(RADIANS(a.Latitude))
* COS(RADIANS(b.Latitude))
* COS(RADIANS(a.Longitude - b.Longitude))
+ SIN(RADIANS(a.Latitude))
* SIN(RADIANS(b.Latitude))))) AS distance_in_km
FROM city AS a
JOIN city AS b ON a.id <> b.id
WHERE a.city = 3 AND b.city = 7
Lưu ý rằng hằng số 111.1111
là số km trên một độ vĩ độ, dựa trên định nghĩa cũ của Napoléon về mét là một phần mười nghìn khoảng cách từ xích đạo đến cực. Định nghĩa đó đủ gần cho công việc của công cụ tìm vị trí.
Nếu bạn muốn dặm theo quy chế thay vì km, hãy sử dụng 69.0
thay vào đó.
http://sqlfiddle.com/#!9/21e06/412/0
Nếu bạn đang tìm kiếm các điểm lân cận, bạn có thể bị cám dỗ sử dụng một mệnh đề như sau:
HAVING distance_in_km < 10.0 /* slow ! */
ORDER BY distance_in_km DESC
Đó là (như chúng tôi nói gần Boston MA Hoa Kỳ) chậm một cách xấu xa.
Trong trường hợp đó, bạn cần sử dụng tính toán hộp giới hạn. Xem bài viết này về cách làm điều đó. http://www.plumislandmedia.net/mysql/haversine-mysql- địa điểm gần nhất /
Công thức chứa LEAST()
hàm số. Tại sao? Vì ACOS()
hàm ném ra một lỗi nếu đối số của nó thậm chí lớn hơn 1. Khi hai điểm được đề cập rất gần nhau, biểu thức với COS()
và SIN()
các phép tính đôi khi có thể mang lại giá trị lớn hơn 1 một chút do epsilon dấu phẩy động (không chính xác
). LEAST(1.0, dirty-great-expression)
cuộc gọi đối phó với vấn đề đó.
Có một cách tốt hơn, công thức
bởi Thaddeus Vincenty
. Nó sử dụng ATAN2()
chứ không phải là ACOS()
vì vậy nó ít bị các sự cố epsilon hơn.