Mysql
 sql >> Database >  >> RDS >> Mysql

Ordinamento delle query MySQL per latitudine/longitudine

Ricordi Pitagora?

$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))";

Tecnicamente questo è il quadrato della distanza invece della distanza effettiva, ma dal momento che lo stai solo usando per l'ordinamento non importa.

Questo utilizza la formula della distanza planare, che dovrebbe essere buona su piccole distanze.

COMUNQUE:

Se vuoi essere più preciso o utilizzare distanze maggiori, usa questa formula per grandi distanze circolari in radianti :

dist = acos[ sin(lat1)*sin(lat2)+cos(lat1)*cos(lat2)*cos(lng1-lng2) ]

(Per ottenere la distanza in unità reali anziché in radianti, moltiplicala per il raggio della Terra. Tuttavia, non è necessario ai fini dell'ordine.)

Il motore di calcolo MySQL presuppone che latitudine e longitudine siano in radianti, quindi se è memorizzata in gradi (e probabilmente lo è), dovrai moltiplicare ciascun valore per pi/180, circa 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))";

o anche:

$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))";