sql >> Databasteknik >  >> RDS >> Mysql

Fråga punkter inom en given radie i MySQL

För MySQL 5.7+

Med tanke på att vi har följande enkla tabell,

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

create spatial index example_lnglat 
    on example (lnglat);

Med följande enkla data,

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

Du skulle få punkterna inom ett givet intervall för en annan punkt (obs:vi måste söka inuti en polygon) med följande kombination av st-funktioner:

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

Du bör se något liknande som ett resultat:

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

För referens på avstånd, om vi tar bort begränsningen ser resultatet för testpunkten ut så här:

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

Anmärkning 1 :fältet kallas lnglat eftersom det är rätt ordning om du tänker på punkter som (x, y) och är också den ordning som de flesta funktioner (som punkt) accepterar parametern

Anmärkning 2 :du kan faktiskt inte dra fördel av rumsliga index om du skulle använda cirklar; Observera också att punktfältet kan ställas in för att acceptera null men rumsliga index kan inte indexera det om det är nullbart (alla fält i indexet måste vara icke-null).

Anmärkning 3 :st_buffer anses (av dokumentationen) vara dålig för detta användningsfall

Anmärkning 4 :funktionerna ovan (särskilt st_distance_sphere) är dokumenterade som snabba men inte nödvändigtvis supernoggranna; om din data är superkänslig för det, lägg till lite rörelseutrymme i sökningen och finjustera resultatuppsättningen



  1. Intervju med Oren Eini på RavenDB om databashantering, analys &säkerhet

  2. MySQL C# asynkmetoder fungerar inte?

  3. JSON_OBJECT() – Skapa ett JSON-objekt från en lista med nyckel-/värdepar i MySQL

  4. Docker - Hur kan man köra kommandot psql i postgres-behållaren?