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

Есть 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). Собственно по этому и пришлось перейти на хранение значений долготы и широты в разных полях.
  • Вопрос задан
  • 14284 просмотра
Решения вопроса 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
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы
SaveTime Москва
от 140 000 до 200 000 руб.
Договор24 Казань
от 60 000 до 120 000 руб.
22 февр. 2019, в 20:42
400 руб./в час
22 февр. 2019, в 20:23
2000 руб./за проект
22 февр. 2019, в 19:31
15000 руб./за проект