sql >> Base de Datos >  >> RDS >> Mysql

Ordenar la consulta MySQL por Latitud/Longitud

¿Recuerdas a Pitágoras?

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

Técnicamente, ese es el cuadrado de la distancia en lugar de la distancia real, pero dado que solo lo estás usando para ordenar, eso no importa.

Esto utiliza la fórmula de distancia planar, que debería ser buena en distancias pequeñas.

SIN EMBARGO:

Si desea ser más preciso o usar distancias más largas, use esta fórmula para distancias de gran círculo en radianes :

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

(Para obtener la distancia en unidades reales en lugar de radianes, multiplíquela por el radio de la Tierra. Sin embargo, eso no es necesario para ordenar).

El motor de cálculo de MySQL asume que la latitud y la longitud están en radianes, por lo que si está almacenada en grados (y probablemente lo esté), tendrá que multiplicar cada valor por pi/180, aproximadamente 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 incluso:

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