Mysql
 sql >> Base de données >  >> RDS >> Mysql

Trier la requête MySQL par Latitude/Longitude

Vous vous souvenez de Pythagore ?

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

Techniquement, c'est le carré de la distance au lieu de la distance réelle, mais puisque vous ne l'utilisez que pour le tri, cela n'a pas d'importance.

Cela utilise la formule de distance plane, qui devrait être bonne sur de petites distances.

CEPENDANT :

Si vous voulez être plus précis ou utiliser des distances plus longues, utilisez cette formule pour les distances orthodromiques en radians :

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

(Pour obtenir la distance en unités réelles au lieu de radians, multipliez-la par le rayon de la Terre. Ce n'est cependant pas nécessaire à des fins de commande.)

La latitude et la longitude sont supposées par le moteur de calcul MySQL être en radians, donc si elles sont stockées en degrés (et c'est probablement le cas), vous devrez multiplier chaque valeur par pi/180, soit environ 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))";

ou encore :

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