Le secteur de la recherche dans un rayon donné dans MySQL
-
18-09-2019 - |
Question
J'ai créé la table MySQL suivante pour stocker les coordonnées latitude / longitude avec un nom pour chaque point:
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;
Je suis en train d'interroger:
- tous les points dans un n rayon de mile d'un point donné;
- la distance de chaque point de retour à partir du point donné
Tous les exemples que j'ai trouvé référence à l'aide d'un rectangle de délimitation minimum (MBR) plutôt qu'un rayon. Le tableau contient environ 1 million de points, donc ce besoin doit être aussi efficace que possible.
La solution 2
Merci à vous deux pour vos réponses.
J'ai finalement trouvé la solution à http: //www.movable -type.co.uk/scripts/latlong-db.html.
Autres conseils
Pour MySQL 5.7 +
Étant donné que nous avons une table simple,
create table example (
id bigint not null auto_increment primary key,
lnglat point not null
);
create spatial index example_lnglat
on example (lnglat);
Avec les données simples suivantes,
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));
Vous obtiendrez des points dans une plage donnée d'un autre point (note: nous devons rechercher à l'intérieur d'un polygone) avec la combinaison suivante de fonctions 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);
Vous devriez voir quelque chose comme ceci comme résultat:
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
Pour référence sur la distance, si on enlève la contrainte le résultat du point de test ressemble à ceci:
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
Note 1 : le champ est appelé lnglat puisque c'est l'ordre correct si vous pensez des points que (x, y) et est également l'ordre la plupart des fonctions (comme le point) accepter le paramètre
Note 2 : vous ne pouvez pas réellement parti des index spatiaux si vous deviez utiliser des cercles; noter également que le champ de point peut être configuré pour accepter les index nuls, mais l'espace ne peut pas indexer si elle est annulable (tous les champs de l'index doivent être non nulle).
Note 3 : ST_Buffer est considéré (par la documentation) pour être mauvais pour ce cas d'utilisation
Note 4 : les fonctions ci-dessus (en particulier st_distance_sphere) sont documentés aussi vite, mais pas nécessairement super précis; si vos données est super sensible à cette ajouter un peu de marge de manœuvre à la recherche et faire des réglages fins à l'ensemble des résultats
Rayon n'est pas efficace indexables. Vous devez utiliser le rectangle de sélection pour obtenir rapidement les points que vous recherchez probablement, puis filtrer les points à l'extérieur du rayon.
Je fait que, pour un point à l'intérieur du cercle de rayon
SELECT
*
FROM
`locator`
WHERE
SQRT(POW(X(`center`) - 49.843317 , 2) + POW(Y(`center`) - 24.026642, 2)) * 100 < `radius`
détails et une requête plus échantillon ici http : //dexxtr.com/post/83498801191/how-to-determine-point-inside-circle-using-mysql, espérons que cette aide