sql >> Database >  >> RDS >> Mysql

Querypunten binnen een bepaalde straal in MySQL

Voor MySQL 5.7+

Aangezien we de volgende eenvoudige tabel hebben,

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

create spatial index example_lnglat 
    on example (lnglat);

Met de volgende eenvoudige gegevens,

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));

Je zou de punten binnen een bepaald bereik van een ander punt krijgen (let op:we moeten binnen een polygoon zoeken) met de volgende combinatie van st-functies:

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);

Je zou zoiets als dit moeten zien:

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

Ter referentie op afstand, als we de beperking verwijderen, ziet het resultaat voor het testpunt er als volgt uit:

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

Opmerking 1 :het veld heet lnglat omdat dat de juiste volgorde is als je aan punten denkt als (x, y) en het is ook de volgorde waarin de meeste functies (zoals punt) de parameter accepteren

Opmerking 2 :je kunt niet echt profiteren van ruimtelijke indexen als je cirkels zou gebruiken; Houd er ook rekening mee dat het puntveld kan worden ingesteld om null te accepteren, maar ruimtelijke indexen kunnen het niet indexeren als het nullable is (alle velden in de index moeten niet-null zijn).

Opmerking 3 :st_buffer wordt (door de documentatie) beschouwd als slecht voor deze use case

Opmerking 4 :de bovenstaande functies (in het bijzonder st_distance_sphere) zijn gedocumenteerd als snel, maar niet noodzakelijk supernauwkeurig; als je gegevens daar supergevoelig voor zijn, voeg dan wat speelruimte toe aan de zoekopdracht en verfijn de resultatenset



  1. Hoe kan ik alle kolommen in een tabel doorzoeken?

  2. DATEDIFF() Voorbeelden – MySQL

  3. Verbinding maken met MySQL veroorzaakt fout Gegevensbronnaam niet gevonden en geen standaardstuurprogramma opgegeven

  4. SQL IN Clausule 1000 itemlimiet