Bạn có một tài liệu tham khảo khá tốt ở đó để tìm kiếm khoảng cách mySQL.
Quên những thứ về Oracle Spatial. Quá nhiều mã, quá nhiều phức tạp, không đủ giá trị gia tăng.
Đây là một truy vấn sẽ thực hiện thủ thuật. Điều này sử dụng khoảng cách tính bằng dặm theo quy chế. CHỈNH SỬA Điều này sẽ sửa lỗi được mdarwin đề cập, với chi phí là kiểm tra phân chia nếu bạn cố gắng sử dụng nó cho một vị trí ở cực bắc hoặc cực nam.
SELECT id, city, LATITUDE, LONGITUDE, distance
FROM
(
SELECT id,
city,
LATITUDE, LONGITUDE,
(3959 * ACOS(COS(RADIANS(LATITUDE))
* COS(RADIANS(mylat))
* COS(RADIANS(LONGITUDE) - RADIANS(mylng))
+ SIN(RADIANS(LATITUDE))
* SIN(RADIANS(mylat))
))
AS distance,
b.mydst
FROM Cities
JOIN (
SELECT :LAT AS mylat,
:LONG AS mylng,
:RADIUS_LIMIT AS mydst
FROM DUAL
)b ON (1 = 1)
WHERE LATITUDE >= mylat -(mydst/69)
AND LATITUDE <= mylat +(mydst/69)
AND LONGITUDE >= mylng -(mydst/(69 * COS(RADIANS(mylat))))
AND LONGITUDE <= mylng +(mydst/(69 * COS(RADIANS(mylat))))
)a
WHERE distance <= mydst
ORDER BY distance
Nếu bạn đang làm việc theo km, hãy thay đổi mydst / 69 thành mydst / 111.045 và thay đổi 3959 thành 6371.4. (1/69 chuyển đổi dặm thành độ; 3959 là một giá trị cho bán kính của hành tinh.)
Bây giờ, bạn có thể bị cám dỗ để sử dụng truy vấn lớn này như một "hộp đen ma thuật". Đừng làm điều đó! Nó không quá khó hiểu, và nếu bạn hiểu nó, bạn sẽ có thể hoàn thành công việc tốt hơn. Đây là những gì đang xảy ra.
Mệnh đề này là trọng tâm của những gì làm cho truy vấn nhanh chóng. Nó tìm kiếm bảng Thành phố của bạn cho các thành phố lân cận đến điểm bạn đã chỉ định.
WHERE LATITUDE >= mylat -(mydst/69)
AND LATITUDE <= mylat +(mydst/69)
AND LONGITUDE >= mylng -(mydst/(69 * COS(RADIANS(mylat))))
AND LONGITUDE <= mylng +(mydst/(69 * COS(RADIANS(mylat))))
Để nó hoạt động, bạn chắc chắn cần một chỉ mục trên cột LATITUDE của mình. Chỉ mục trên cột LONGITUDE của bạn cũng sẽ hữu ích một chút. Nó thực hiện một tìm kiếm gần đúng, tìm kiếm các hàng nằm trong một mảnh bán hình chữ nhật trên bề mặt trái đất gần điểm của bạn. Nó chọn quá nhiều thành phố, nhưng không quá nhiều.
Điều khoản này ở đây cho phép bạn loại bỏ các thành phố thừa khỏi tập kết quả của bạn:
WHERE distance <= mydst
Mệnh đề này là công thức hasrsine tính toán khoảng cách vòng tròn lớn giữa mỗi thành phố và điểm của bạn.
(3959 * ACOS(COS(RADIANS(LATITUDE))
* COS(RADIANS(mylat))
* COS(RADIANS(LONGITUDE) - RADIANS(mylng))
+ SIN(RADIANS(LATITUDE))
* SIN(RADIANS(mylat))
Mệnh đề này cho phép bạn nhập điểm và giới hạn bán kính của bạn, chỉ một lần dưới dạng các biến liên kết với truy vấn của bạn. Nó hữu ích vì các công thức khác nhau sử dụng các biến đó nhiều lần.
SELECT :LAT AS mylat,
:LONG AS mylng,
:RADIUS_LIMIT AS mydst
FROM DUAL
Phần còn lại của truy vấn chỉ đơn giản là sắp xếp mọi thứ để bạn chọn và sắp xếp theo khoảng cách.
Đây là lời giải thích đầy đủ hơn: http://www.plumislandmedia.net / mysql / haversine-mysql-near-loc /