Pregunta

He creado la siguiente tabla de MySQL para almacenar latitud / longitud coordina junto con un nombre para cada punto:

CREATE TABLE `points` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(128) NOT NULL,
  `location` point NOT NULL,
  PRIMARY KEY (`id`),
  SPATIAL KEY `location` (`location`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;

Estoy tratando de consultar:

  • todos los puntos dentro de un n radio de millas de un punto dado;
  • la distancia de cada punto de regresar del punto dado

Todos los ejemplos que he encontrado se refieren a la utilización de un rectángulo delimitador mínimo (MBR) en lugar de un radio. La tabla contiene aproximadamente 1 millón de puntos, por lo que esta necesidad debe ser lo más eficiente posible.

¿Fue útil?

Solución 2

gracias a ambos por sus respuestas.

Al final encontré la solución en http: //www.movable -type.co.uk/scripts/latlong-db.html.

Otros consejos

Para MySQL 5.7 +

Dado que tenemos la siguiente tabla sencilla,

create table example (
  id bigint not null auto_increment primary key,
  lnglat point not null
);

create spatial index example_lnglat 
    on example (lnglat);

Con los siguientes datos sencilla,

insert into example (lnglat) 
values
(point(-2.990435, 53.409246)),
(point(-2.990037, 53.409471)),
(point(-2.989736, 53.409676)),
(point(-2.989554, 53.409797)),
(point(-2.989350, 53.409906)),
(point(-2.989178, 53.410085)),
(point(-2.988739, 53.410309)),
(point(-2.985874, 53.412656)),
(point(-2.758019, 53.635928));

Puede conseguir los puntos dentro de un rango determinado de otro punto (nota: tenemos que buscar dentro de un polígono) con la siguiente combinación de funciones st:

set @px = -2.990497;
set @py = 53.410943;
set @range = 150; -- meters
set @rangeKm = @range / 1000;

set @search_area = st_makeEnvelope (
  point((@px + @rangeKm / 111), (@py + @rangeKm / 111)),
  point((@px - @rangeKm / 111), (@py - @rangeKm / 111))
);

select id, 
       st_x(lnglat) lng, 
       st_y(lnglat) lat,
       st_distance_sphere(point(@px, @py), lnglat) as distance
  from example
 where st_contains(@search_area, lnglat);

Debería ver algo como esto como resultado:

3   -2.989736   53.409676   149.64084252776277
4   -2.989554   53.409797   141.93232714661812
5   -2.98935    53.409906   138.11516275402533
6   -2.989178   53.410085   129.40289289527473

Para tener una referencia de la distancia, si quitamos la restricción del resultado para el punto de prueba se parece a esto:

1   -2.990435   53.409246   188.7421181457556
2   -2.990037   53.409471   166.49406509160158
3   -2.989736   53.409676   149.64084252776277
4   -2.989554   53.409797   141.93232714661812
5   -2.98935    53.409906   138.11516275402533
6   -2.989178   53.410085   129.40289289527473
7   -2.988739   53.410309   136.1875540498202
8   -2.985874   53.412656   360.78532732013963
9   -2.758019   53.635928   29360.27797292756

Nota 1 : el campo se llama lnglat ya que es el orden correcto si se piensa en puntos como (x, y) y es también el orden mayoría de las funciones (como puntos) aceptar el parámetro

Nota 2 : no se puede realmente tomar ventaja de los índices espaciales si se fuera a utilizar círculos; También tenga en cuenta que el campo de punto se puede configurar para aceptar nulos índices espaciales, pero no pueden indexar que si es anulable (se requieren todos los campos en que el índice sea no nulo).

Nota 3 : ST_Buffer se considera (en la documentación) a ser malo para este caso de uso

Nota 4 : las funciones anteriores (en particular st_distance_sphere) se documentan tan rápido pero no necesariamente súper precisa; Si los datos son muy sensibles a los que añadir un poco de margen de maniobra para la búsqueda y hacer algunos ajustes para el conjunto de resultados

Radio no es eficiente indexable. Debe utilizar el rectángulo delimitador para obtener rápidamente los puntos que probablemente está buscando, y luego filtrar los puntos fuera del radio.

Lo hice durante un punto en el interior del círculo con radio

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

detalles y una muestra más consulta aquí http : //dexxtr.com/post/83498801191/how-to-determine-point-inside-circle-using-mysql , espero que esta ayuda

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top