Interroga i punti entro un determinato raggio in MySQL
-
18-09-2019 - |
Domanda
Ho creato la seguente tabella MySQL per memorizzare le coordinate di latitudine/longitudine insieme a un nome per ciascun 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;
Sto cercando di interrogare:
- tutti i punti all'interno di an N raggio in miglia di un dato punto;
- la distanza di ciascun punto restituito dal punto specificato
Tutti gli esempi che ho trovato si riferiscono all'utilizzo di un rettangolo di delimitazione minima (MBR) anziché di un raggio.La tabella contiene circa 1 milione di punti, quindi questa esigenza deve essere quanto più efficiente possibile.
Soluzione 2
Vi ringrazio entrambi per le vostre risposte.
Alla fine ho trovato la soluzione a http: //www.movable -type.co.uk/scripts/latlong-db.html.
Altri suggerimenti
Per MySQL 5.7 +
Dato che abbiamo la seguente semplice tabella,
create table example (
id bigint not null auto_increment primary key,
lnglat point not null
);
create spatial index example_lnglat
on example (lnglat);
Con i seguenti dati semplice,
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));
Si potrebbe ottenere i punti entro un determinato intervallo di un altro punto (nota: dobbiamo cercare all'interno di un poligono) con la seguente combinazione di funzioni 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);
Si dovrebbe vedere qualcosa di simile a questo come un risultato:
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
Per riferimento alla distanza, se togliamo il vincolo del risultato del punto di prova si presenta così:
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 : il campo si chiama lnglat dato che è l'ordine corretto se si pensa di punti come (x, y) ed è anche l'ordine maggior parte delle funzioni (come punto) accettare il parametro
Nota 2 : non si può effettivamente usufruire dei indici spaziali, se si sceglie di usare i cerchi; anche notare che il campo punto può essere impostato per accettare indici nulli ma spaziali non può indicizzare se è annullabile (tutti i campi nell'indice devono essere non nullo).
Nota 3 : ST_Buffer è considerato (dalla documentazione) per essere un male per questo caso d'uso
Nota 4 : le funzioni di cui sopra (in particolare st_distance_sphere) sono documentati più veloce, ma non necessariamente super-accurate; se i dati è super sensibile a che aggiungono un po 'di spazio di manovra per la ricerca e fare qualche messa a punto per il set di risultati
Raggio non è efficiente indicizzabile. Si dovrebbe usare il rettangolo di delimitazione per ottenere rapidamente i punti si sono probabilmente cercando, e poi filtrare punti al di fuori del raggio.
L'ho fatto per un punto all'interno del cerchio con raggio
SELECT
*
FROM
`locator`
WHERE
SQRT(POW(X(`center`) - 49.843317 , 2) + POW(Y(`center`) - 24.026642, 2)) * 100 < `radius`
dettagli e un'altra query di esempio qui http://dexxtr.com/post/83498801191/how-to-determine-point-inside-circle-using-mysql, spero che questo ti aiuti