Como explique en la primera parte del calculo de distancias hay un cierto problema en calcular distancias cuando tienes un numero elevado de registros en la base de datos. Es decir, necesitamos limitar nuestros cálculos para no realizar un numero elevado de operaciones aritméticas. Ademas estas distancias tenemos que ordenar después en un vector, si queremos presentarlas decentemente.
El sentido común nos indica que es mejor calcular 50 localizaciones que 5000. Aunque desempolvando mis estudios de complejidad, si no me equivoco seria constante o kN. De hecho el simple hecho de ordenarlo después tiene mas complejidad, en el peor de los casos N*N… en fin, que alguien me corrija si eso. Lógicamente si quieres presentar un resultado ordenado, no es lo mismo ordenar 50 que 500 resultados. Recuerda que PHP tiene funciones para eso.
Un grado de Latitud o Longitud en decimal equivale a 111 kilómetros
Basandose en esta afirmación, basada en la definición de latitud, podemos acotar nuestra búsqueda MySQL en un determinado radio utilizando una simple constante con BETWEEN (desgraciadamente MySQL no tiene de eso y hay que utilizar comparaciones). Por ejemplo una constante de 0.1 grados seria equivalente a un radio de 11 kilómetros, 0.2 serian 22 kms… etc.
$constante = 0.2; $lat_min = $latitud - $constante; $lat_max = $latitud + $constante; $lng_min = $longitud - $constante; $lng_max = $longitud + $constante;
Después lo único que hay que hacer es acotar la consulta por valores inferiores de latitud y longitud…
$query = "SELECT * " . "FROM `municipios`" . "WHERE `latitud` >= {$lat_min} AND " . "`latitud` <= {$lat_max} AND " . "`longitud` >= {$lng_min} AND " . "`longitud` <= {$lng_max}";
El ejemplo completo con mis pruebas lo tengo subido a github. Ahí encontraras el código completo del ejemplo con una base de datos de municipios, provincias y comunidades autónomas. Clase para conectarse a MySQL, formula de Haversine en PHP y algunos test y comprobaciones. Cabe destacar que algunos municipios de Madrid tienen mal las coordenadas, de hecho me he dado cuenta al calcular las distancias.
Otras posibilidades de acotar, quizás menos eficientes.
Seguramente habrás pensado seleccionar solo municipios de una sola provincia, código postal o región. Sin embargo trabajar con radio es mucho mas preciso. Imaginate un restaurante en un municipio justo en la frontera de la provincia. Si lo comparamos con todos los restaurantes de esa provincia nos olvidamos de los que se encuentran en la adyacente y ademas puedes resultar mucho mas cercanos. Lo mismo pasa con el código postal…
6 respuestas a «Calcular distancias y lugares similares con PHP y MySQL en un radio determinado»
[…] Newer Older […]
Está muy bien pero tiene un inconveniente, que calculas en línea recta tanto en horizontal como vertical y normalmente al comparar 2 puntos en un mapa para saber la distancia tendrías que aplicar trigonometría ya que la distancia dentro de los margenes que se han puesto para los catetos (altura y longitud) sería superada por la hipotenusa, con lo cual, las busquedas no estarían acotando correctamente que la distancia máxima se aplique podrá ser superada casi siempre.
¿No seria mucho mas rápido usar BETWEEN?
Si hay BETWEEN en MySQL, lo uso a diario con fechas, es mucho mas rápido.
http://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_between
http://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_between
Q si jeje tengo pendiente corregir el post desde hace como 2 años sorry. De hecho juraría que ya lo había corregido… pero resulta que no 😐 De hecho a día de hoy no se por que cojones había escrito eso. En fin algún día lo cambio ahí y en el código también.