Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Classificando a consulta do MySQL por Latitude/Longitude


Lembra de 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))";

Tecnicamente, esse é o quadrado da distância em vez da distância real, mas como você está usando apenas para classificar, isso não importa.

Isso usa a fórmula da distância planar, que deve ser boa em pequenas distâncias.

Entretanto:

Se você quiser ser mais preciso ou usar distâncias maiores, use esta fórmula para grandes distâncias de círculo em radianos :
dist = acos[ sin(lat1)*sin(lat2)+cos(lat1)*cos(lat2)*cos(lng1-lng2) ]

(Para obter a distância em unidades reais em vez de radianos, multiplique-a pelo raio da Terra. No entanto, isso não é necessário para fins de ordenação.)

A latitude e a longitude são assumidas pelo mecanismo de computação do MySQL em radianos, portanto, se for armazenado em graus (e provavelmente é), você terá 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))";

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