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.

Était-ce utile?

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top