sql >> Database teknologi >  >> RDS >> Mysql

Geolocation MySQL-forespørgsel

Problemet er, at den måde, du gemmer data på i databasen, ikke er egnet til den type opgave, du udfører. Brug af Point værdier i Geometry datapunkter er vejen at gå. Faktisk kodet noget 4+ år tilbage til dette formål, men har problemer med at finde det. Men dette indlæg synes at dække det godt.

REDIGER Okay, fandt min gamle kode, men den henviser til gamle klientdata, som jeg åbenbart ikke kan dele. Men nøglen til hastighed med koordinater i databaser er at bruge POINT data gemt i databasetabellen med typen GEOMETRY . Flere detaljer her på den officielle MySQL-side. Da jeg i et stykke tid har haft brug for en grund til at gense denne type kode – og koncepterne – er her et hurtigt MySQL-script, jeg har lavet en prøvetabel med eksempeldata for at formidle de grundlæggende koncepter. Når du først forstår, hvad der sker, åbner det op for mange fede muligheder.

Fandt også denne gode/enkle forklaring også af konceptet.

Og fandt en anden stor vurdering af geografiske data i MySQL 5.6. Masser af god information om indekser og ydeevne. Specifikt vedrørende MySQL rumlige indeksydelse:

Og på den anden side af det:

Og her er mine grundlæggende MySQL-testscripts for at hjælpe med at illustrere konceptet:

/* Create the database `spatial_test` */
CREATE DATABASE `spatial_test` CHARACTER SET utf8 COLLATE utf8_general_ci;

/* Create the table `locations` in `spatial_test` */
CREATE TABLE `spatial_test`.`locations` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `coordinates` point NOT NULL,
  UNIQUE KEY `id` (`id`),
  SPATIAL KEY `idx_coordinates` (`coordinates`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

/* Insert some test data into it. */
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(27.174961 78.041822)'));
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(27.985818 86.923596)'));
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(44.427963 -110.588455)'));
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(19.896766 -155.582782)'));
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(40.748328 -73.985560)'));
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(40.782710 -73.965310)'));

/* A sample SELECT query that extracts the 'latitude' & 'longitude' */
SELECT x(`spatial_test`.`locations`.`coordinates`) AS latitude, y(`spatial_test`.`locations`.`coordinates`) AS longitude FROM `spatial_test`.`locations`;

/* Another sample SELECT query calculates distance of all items in database based on GLength using another set of coordinates. */
SELECT GLength(LineStringFromWKB(LineString(GeomFromText(astext(PointFromWKB(`spatial_test`.`locations`.`coordinates`))), GeomFromText(astext(PointFromWKB(POINT(40.782710,-73.965310))))))) AS distance
FROM `spatial_test`.`locations`
;

/* Yet another sample SELECT query that selects items by using the Earth’s radius. The 'HAVING distance < 100' equates to a distance of less than 100 miles or kilometers based on what you set the query for. */
/* Earth’s diameter in kilometers: 6371 */
/* Earth’s diameter in miles: 3959 */
SELECT id, (3959 * acos(cos(radians(40.782710)) * cos(radians(x(`spatial_test`.`locations`.`coordinates`))) * cos(radians(y(`spatial_test`.`locations`.`coordinates`)) - radians(-73.965310)) + sin(radians(40.782710)) * sin(radians(x(`spatial_test`.`locations`.`coordinates`))))) AS distance 
FROM `spatial_test`.`locations`
HAVING distance < 100
ORDER BY id
;



  1. Tilslutning af Google Spreadsheets til MySQL m/ JDBC

  2. Hvorfor gemmer sql-server tegn på spørgsmålstegn i stedet for japanske tegn i NVarchar-felter?

  3. Common Sense-licensændringer til SQL Server 2014 Standard Edition

  4. Bedste praksis for at oprette indekser på dine MySQL-tabeller – Rullende indeksbygninger