Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Geolocation-MySQL-Abfrage

Das Problem ist, dass die Art und Weise, wie Sie Daten in der Datenbank speichern, nicht für die Art der Aufgabe geeignet ist, die Sie ausführen. Mit Point Werte in Geometry Datenpunkte ist der Weg zu gehen. Eigentlich habe ich vor über 4 Jahren etwas für diesen Zweck codiert, habe aber Probleme, es zu finden. Aber dieser Beitrag scheint es gut abzudecken.

BEARBEITEN Okay, ich habe meinen alten Code gefunden, aber er bezieht sich auf alte Kundendaten, die ich natürlich nicht teilen kann. Aber der Schlüssel zur Geschwindigkeit mit Koordinaten in Datenbanken ist die Verwendung von POINT Daten, die in der Datenbanktabelle vom Typ GEOMETRY gespeichert sind . Weitere Details hier auf der offiziellen MySQL-Seite. Da ich einen Grund brauchte, um diese Art von Code – und die Konzepte – für eine Weile noch einmal zu betrachten, habe ich hier ein schnelles MySQL-Skript, das ich zusammengestellt habe, um eine Beispieltabelle mit Beispieldaten zu erstellen, um die grundlegenden Konzepte zu vermitteln. Sobald Sie verstehen, was passiert, eröffnen sich viele coole Optionen.

Auch diese tolle/einfache Erklärung des Konzepts.

Und fand eine weitere großartige Bewertung von Geodaten in MySQL 5.6. Viele großartige Informationen zu Indizes und Leistung. Speziell in Bezug auf die räumliche Indexleistung von MySQL:

Und auf der anderen Seite davon:

Und hier sind meine grundlegenden MySQL-Testskripte, um das Konzept zu veranschaulichen:

/* 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
;