2014-01-10 2 views
5

У меня в моей базе 100 000 адресов (это записи).MySQL выбирает координаты в пределах диапазона

Каждый из них имеет свои собственные координаты (широта и долгота).

Теперь, учитывая географическое местоположение пользователя (широта и долгота), я хочу показать на карте только адреса в пределах 5 миль (с использованием API карт Google v3 API).

Это означает, что из 100 000 адресов обычно должно отображаться только 5 или 6 адресов.

Одним из решений может быть извлечение всех записей и применение формулы на Java для расчета расстояния по каждому адресу и отображение его только в том случае, если оно находится внутри диапазона.

Это было бы пустой тратой вычислительной мощности, потому что мне нужно было бы восстановить все записи, когда мне нужно было показать только 5 или 6 из них на карте.

Как решить эту проблему на стороне базы данных (MySQL), чтобы возвращать только адреса в диапазоне 5 миль?

+0

Возможный дубликат [Расчет Haversine: Показать пользователей в комплекте] (http://stackoverflow.com/questions/20437225/haversine-calculation-show-users-within -задавать) –

ответ

0

Я думаю, гео пространственных расширений MySQL была бы решить эту проблему для вас: http://dev.mysql.com/doc/refman/5.7/en/gis-introduction.html

В противном случае вы могли бы индекс Lattitude затем запрос WHERE Lattitude> userLat-5miles и Lattitude < userLat + 5miles. Это значительно уменьшит количество возможных строк для обработки на прикладном уровне.

14

Вы можете использовать то, что называется Haversine formula.

$sql = "SELECT *, (3959 * acos(cos(radians(" . $lat . ")) * cos(radians(lat)) * cos(radians(lng) - radians(" . $lng . ")) + sin(radians(" . $lat . ")) * sin(radians(lat)))) AS distance FROM your_table HAVING distance < 5"; 

Где $lat и $lng координаты вашей точки, и широта/LNG ваши столбцы таблицы. Вышеуказанное будет содержать список местоположений в диапазоне 5 нм. Заменить 3959 на 6371, чтобы перейти в километры.

Эта ссылка может быть полезна: https://developers.google.com/maps/articles/phpsqlsearch_v3

Edit: я не видел, вы упомянули Java. Этот пример находится в PHP, но запрос по-прежнему нужен вам.

0

Mr UpsideDown, я искал ответ на этот вопрос в течение нескольких недель, и есть очень хорошее решение, которое на удивление я нигде не нашел. Вам нужно будет создать хранимую процедуру, ограничить близость с Java до того, как вы примените ее к запросу MySQL, и запрос вернет результаты в вопрос о miliseconds, я использую это в таблице, где есть более чем 900K пользователей и вы можете осуществлять поиск по близости в соответствии 100мс с этой техникой (это объясняется PHP, но фокус в MySQL, что вам нужно, это еще есть):

http://cssshowcase.co.uk/mysql-get-distance-by-latitude-and-longitude-coordinates/

Никакое другое решение не работает так хорошо и так же быстро, как выше, другие решения в Интернете сделали запрос занятием 15-20 секунд, что, очевидно, не очень хорошо.

0

Мой подход - и я использую его - это думать, как техник, я доволен +/- 5%

Это решение не предназначено для управления ракетами, лодки или подобного, и только на расстояниях ниже ~ 100 км его просто решение, как Fermi problem

Так давайте начнем прагматичного решения:

Во-первых: для многих проблем, которые мы можем игнорировать, что земля не является плоской (расстояние < ~ 100 км),

Окружность земли более или менее 40000 км (более или менее точно)

Круг имеет ровно 360 град.

Так 1 км составляет: 360/40000 град => 0,00278 град

А потом просто выбрать широту/долготу в этом 0,003 за км, это будет что-то вроде, где долго> 42 - 0,003 и долго < 42 + 0.003 - то же самое для lat, где 42 - ваш lat/long, как middpoint. В базе данных будут использоваться индексы.

проблема: вы получите квадрат как результат не круг (не реальное расстояние)

Если вам нужен круг, сценарий его после получения результатов.

Я просто показываю официальный туалет в 2 км, поэтому квадрат в порядке, и точность тоже. Причина в том, что есть улицы и дома, так что люди не могут ходить прямо ...

Edit: Техническое/математическое объяснить:

Для очень маленьких треугольников (один угол < < 5 град) вы можете игнорировать использование тригонометрии. Итак, sin (5 град) ~ = 5/180 * PI

Смежные вопросы