Encuentra puntos dentro de una distancia usando MySQL


20

Tengo una tabla mySQL con nombre de usuario, latitud y longitud del usuario. Me gustaría obtener una lista de usuarios que están dentro del círculo o cuadrado de una latitud y longitud dada con una distancia dada. Por ejemplo, mi entrada Lat = 78.3232 y Long = 65.3234 y distancia = 30 millas. Me gustaría obtener la lista de usuarios que están dentro de 30 millas de distancia del punto 78.3232 y 65.3234. ¿Es posible resolver esto con una sola consulta? ¿O puede darme una pista para comenzar a resolver esta consulta? Soy nuevo en la información basada en geo.


¿Por qué no PostGIS? Si está comenzando un proyecto geográfico, aún puede cambiar su pila
simplexio

stackoverflow.com/a/40272394/1281385 Debería ser útil para acelerar esta consulta (si es necesario)
exussum

Respuestas:


32

La instrucción SQL que encontrará las 20 ubicaciones más cercanas dentro de un radio de 30 millas a la coordenada 78.3232, 65.3234. Calcula la distancia en función de la latitud / longitud de esa fila y la latitud / longitud objetivo, y luego solicita solo filas donde el valor de la distancia es inferior a 30 millas, ordena la consulta completa por distancia y la limita a 20 resultados. Para buscar por kilómetros en lugar de millas, reemplace 3959 con 6371.

SELECT
  id, (
    3959 * acos (
      cos ( radians(78.3232) )
      * cos( radians( lat ) )
      * cos( radians( lng ) - radians(65.3234) )
      + sin ( radians(78.3232) )
      * sin( radians( lat ) )
    )
  ) AS distance
FROM markers
HAVING distance < 30
ORDER BY distance
LIMIT 0 , 20;

Esto está utilizando la API de Google Maps v3 con un servidor MySQL que ya tienes.

https://developers.google.com/maps/articles/phpsqlsearch_v3#findnearsql


Recibo un error de sintaxis en mi selección usando esto, "# 1582 - Conteo de parámetros incorrecto en la llamada a la función nativa 'radianes', ¿qué podría ser?
Bluantinoo

Encontrado: ¡Tenía la variable lng vacía! ¡lo siento!
bluantinoo

Exactamente lo que quería, pero ¿cuál es la sobrecarga del rendimiento de la consulta para miles de registros? ¿Y qué hay de la precisión?
Amit Shah

1
mucho mejor reemplazarlo a 6371392.896 para buscar por metros
Vasilii Suricov

34

La respuesta de Mapperz no es válida. El seno debe calcularse a partir de la latitud y NO a partir de la longitud. Entonces, la declaración corect SQL es:

SELECT
    id, (
      3959 * acos (
      cos ( radians(78.3232) )
      * cos( radians( lat ) )
      * cos( radians( lng ) - radians(65.3234) )
      + sin ( radians(78.3232) )
      * sin( radians( lat ) )
    )
) AS distance
FROM markers
HAVING distance < 30
ORDER BY distance
LIMIT 0 , 20;

Su respuesta debe ser ordenada primero.
Amit Shah

@AmitShah Si cree que podría hacer ping al autor de la pregunta (@shihabK que no ha estado activo en el sitio durante casi 6 años) y / o votar por meta.stackexchange.com/questions/268666/…
PolyGeo

Esta debería ser la respuesta aceptada.
catbadger

2

Puede ser base para crear una función ... para que pueda reutilizarla en otras áreas. También haría su consulta un poco más limpia ... Al menos eso son mis 2 centavos.

DELIMITER $$

create function calcDistance(lat float, lng float, pnt_lat float, pnt_lng float)

Returns float
BEGIN

Declare dist float;
SET dist =
  3959 * acos (
  cos ( radians(pnt_lat) )
  * cos( radians( lat ) )
  * cos( radians( lng ) - radians(pnt_lng) )
  + sin ( radians(pnt_lat) )
  * sin( radians( lat ) )
);

RETURN dist;

END

la respuesta será votada si arreglas el estilo de código. es la manera correcta
Vasilii Suricov

0

Aquí está mi variante de consulta, parece un poco más fácil ( http://dexxtr.com/post/83498801191/how-to-determine-point-inside-circle-using-mysql )

SELECT 
    *
FROM 
    `locator`
WHERE
    SQRT(POW(X(`center`) - 49.843317 , 2) + POW(Y(`center`) - 24.026642, 2)) * 100 < `radius`

44
Es más fácil pero ignora el hecho de que la tierra es curva.
Tim Rijavec

Necesita una fórmula para ser precisa. Tal vez esto sería bueno solo en distancias cortas: D
Jethro

¿Vas a lanzar un misil o algo así?
Dennis Braga

1
@DennisBraga: si es así, ¿tal vez esta pregunta esté fuera de tema, más adecuada para http://globalthermonuclearwar.stackexchange.com ...?
Ashleedawg
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.