Выборка ближайших точек?

Есть MySQL база данных со следующей таблицей:


CREATE TABLE IF NOT EXISTS `my_table` (

`id` int(11) unsigned NOT NULL AUTO_INCREMENT,

`name` text NOT NULL,

`longitude` double NOT NULL,

`latitude` double NOT NULL,

PRIMARY KEY (`id`)

) ENGINE=MyISAM DEFAULT CHARSET=utf8;


Необходимо составить запрос на выборку всех записей, которые находятся (по координатам longitude и latitude) в радиусе N метров от точки A (координаты которой известны).


P.S. До этого координаты хранил с помощью типа POINT, но после долгих поисков в интернете понял, что в MySQL очень урезаны возможности работы с этим типом, в отличие, к примеру, от PostgreSQL (PostGIS). Собственно по этому и пришлось перейти на хранение значений долготы и широты в разных полях.
  • Вопрос задан
  • 14619 просмотров
Решения вопроса 1
Ramzeska
@Ramzeska
Используйте функции spatial движка mysql. dev.mysql.com/doc/refman/5.1/en/spatial-extensions.html
Там есть и специальные индексы и оптимизированный поиск по ним. Вам достаточно lat,lng поля превратить в одно поле типа GeoPoint и создать на нем spatial индекс. А далее дело техники сделать выборку в пределах квадрата по индексу и через having отрезать до окружности. Лучше поступать именно так, потому что там используется специальный для этого индекс. Не знаю что там у вас урезано, но мы проверяли быстродействие при поиске по двум полям и по point полю, так последний показал в разы большую производительность.
Ответ написан
Пригласить эксперта
Ответы на вопрос 8
Ramzeska
@Ramzeska
Ну а если вас интересует функция, переводящая две координаты в расстояние между ними, с радостью поделюсь кусочком:
<?php
    private function LatLngDist($p, $q) {
        $R = 6371; // Earth radius in km

        $dLat = (($q[0] - $p[0]) * pi() / 180);
        $dLon = (($q[1] - $p[1]) * pi() / 180);
        $a = sin($dLat / 2) * sin($dLat / 2) +
                cos($p[0] * pi() / 180) * cos($q[0] * pi() / 180) *
                sin($dLon / 2) * sin($dLon / 2);
        $c = 2 * atan2(sqrt($a), sqrt(1 - $a));

        return $R * $c;
    }
Ответ написан
BuriK666
@BuriK666
Компьютерный псих
Если не учитывать то, что это координаты на поверхности геоида, а считать координатами на плоскости, то подойдет теорема Пифагора.
В прямоугольном треугольнике квадрат длины гипотенузы равен сумме квадратов длин катетов.

SQRT(POW(latitude-latitudeA,2)+POW(longitude-longitudeA,2))<N
Ответ написан
m08pvv
@m08pvv
Если точек много и хранятся так, то можно попробовать разбить на квадраты и по координатам сначала получать квадрат и его соседей, а затем перебирать только их, ну и считать можно квадрат расстояния (корень всё-таки долго извлекать, а обойтись можно и без этого)
Ответ написан
@Vampiro
Я делал выборку квадрата со стороной в 2 радиуса запросом, а более точно для каждой точки считал расстояния в серверной части приложения. Так проще масштабировать и будут индексы задействованы.
Ответ написан
Gasoid
@Gasoid
мой подобный вопрос: habrahabr.ru/qa/23016/

По оптимизации поиска по вхождению точки в квадрат для Mysql
www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL
Ответ написан
@tribesman
Вывод точек с сортировкой - "сначала те, которые ближе к точке по адресу Москва, ул Народного Ополчения."
SELECT *,
(ABS(lon-37.48488200)+ABS(lat-55.78553900)) as crd
FROM `pvz`
#WHERE `ds_full_addr` LIKE '%Народного%'
ORDER BY `crd` ASC
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы