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.