Pamiętasz Pitagorasa?
$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))";
Technicznie jest to kwadrat odległości zamiast rzeczywistej odległości, ale ponieważ używasz go tylko do sortowania, nie ma to znaczenia.
Wykorzystuje to wzór na odległość planarną, która powinna być dobra na małych odległościach.
JEDNAK:
Jeśli chcesz być bardziej precyzyjny lub użyć dłuższych odległości, użyj tego wzoru na duże odległości po okręgu w radianach :
dist = acos[ sin(lat1)*sin(lat2)+cos(lat1)*cos(lat2)*cos(lng1-lng2) ]
(Aby uzyskać odległość w rzeczywistych jednostkach zamiast w radianach, pomnóż ją przez promień Ziemi. Nie jest to jednak konieczne do celów porządkowania.)
Silnik obliczeniowy MySQL zakłada, że szerokość i długość geograficzna są wyrażone w radianach, więc jeśli są przechowywane w stopniach (i prawdopodobnie tak jest), będziesz musiał pomnożyć każdą wartość przez pi/180, około 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))";
a nawet:
$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))";