Nhớ Pythagoras?
$sql = "SELECT * FROM table
WHERE lon BETWEEN '$minLon' AND '$maxLon'
AND lat BETWEEN '$minLat' AND '$maxLat'
ORDER BY (POW((lon-$lon),2) + POW((lat-$lat),2))";
Về mặt kỹ thuật, đó là bình phương của khoảng cách thay vì khoảng cách thực, nhưng vì bạn chỉ sử dụng nó để phân loại nên không quan trọng.
Điều này sử dụng công thức khoảng cách phẳng, sẽ tốt trong khoảng cách nhỏ.
TUY NHIÊN:
Nếu bạn muốn chính xác hơn hoặc sử dụng khoảng cách xa hơn, hãy sử dụng công thức này cho khoảng cách vòng tròn lớn tính bằng radian :
dist = acos[ sin(lat1)*sin(lat2)+cos(lat1)*cos(lat2)*cos(lng1-lng2) ]
(Để tính khoảng cách theo đơn vị thực thay vì radian, hãy nhân nó với bán kính Trái đất. Tuy nhiên, điều đó không cần thiết cho mục đích sắp xếp.)
Vĩ độ và kinh độ được công cụ tính toán MySQL giả định là radian, vì vậy nếu nó được lưu trữ bằng độ (và có thể là như vậy), bạn sẽ phải nhân từng giá trị với pi / 180, xấp xỉ 0,01745:
$sf = 3.14159 / 180; // scaling factor
$sql = "SELECT * FROM table
WHERE lon BETWEEN '$minLon' AND '$maxLon'
AND lat BETWEEN '$minLat' AND '$maxLat'
ORDER BY ACOS(SIN(lat*$sf)*SIN($lat*$sf) + COS(lat*$sf)*COS($lat*$sf)*COS((lon-$lon)*$sf))";
hoặc thậm chí:
$sf = 3.14159 / 180; // scaling factor
$er = 6350; // earth radius in miles, approximate
$mr = 100; // max radius
$sql = "SELECT * FROM table
WHERE $mr >= $er * ACOS(SIN(lat*$sf)*SIN($lat*$sf) + COS(lat*$sf)*COS($lat*$sf)*COS((lon-$lon)*$sf))
ORDER BY ACOS(SIN(lat*$sf)*SIN($lat*$sf) + COS(lat*$sf)*COS($lat*$sf)*COS((lon-$lon)*$sf))";