PHP / MySQL: выбор местоположения, близкого к заданному местоположению из БД - PullRequest
8 голосов
/ 21 мая 2009

В PHP у меня есть следующий код для расчета расстояния между двумя точками:

<?php
function distance($lat1, $long1, $lat2, $long2) {
    // DEGREE TO RADIAN
    $latitude1 = $lat1/180*pi();
    $longitude1 = $long1/180*pi();
    $latitude2 = $lat2/180*pi();
    $longitude2 = $long2/180*pi();
    // FORMULA: e = ARCCOS ( SIN(Latitude1) * SIN(Latitude2) + COS(Latitude1) * COS(Latitude2) * COS(Longitude2-Longitude1) ) * EARTH_RADIUS
    $distance = acos(sin($latitude1)*sin($latitude2)+cos($latitude1)*cos($latitude2)*cos($longitude2-$longitude1))*6371;
    return $distance;
}
echo distance(9.9921962, 53.5534074, 9.1807688, 48.7771056); // Hamburg, DE - Stuttgart, DE
?>

Но теперь я хочу выбрать местоположения, близкие к данному местоположению через PHP, из моей базы данных MySQL:

  • Пользователь входит в свой родной город
  • Мой скрипт получает значения широты / долготы через Google API
  • В моей базе данных есть около 200 местоположений с полем для значения широты и полем для значения долготы
  • Мне нужен код для PHP и MySQL, чтобы выбрать 10 мест, наиболее близких к родному городу пользователя

Надеюсь, вы мне поможете. Заранее спасибо!

Ответы [ 7 ]

8 голосов
/ 24 мая 2009

MySQL Great Circle Distance (формула Haversine) делает именно то, что вам нужно.

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

Расчет расстояния между почтовыми индексами в PHP имеет несколько реализаций PHP этого алгоритма.

Поиск географического приближения почти такая же проблема, как и у вас.

4 голосов
/ 24 мая 2009

Может быть, что-то вроде

SELECT field1, field2, ...,
    ACOS(SIN(latitude / 180 * PI()) * SIN(:1) + COS(latitude / 180 * PI()) * COS(:2) * COS(:2 - longtidude)) * 6371 AS distance
    ORDER BY distance ASC;

или

SELECT field1, field2, ...,
    ACOS(SIN(RADIANS(latitude)) * SIN(:1) + COS(RADIANS(latitude)) * COS(:2) * COS(:2 - longtidude)) * 6371 AS distance
    ORDER BY distance ASC;

(напрямую переведено из кода PHP)

:1 и :2 - это $lat2/180*pi() и $long2/180*pi() соответственно.

1 голос
/ 24 мая 2009

Это формула Haversine. Вы можете перевести PHP напрямую в SQL, чтобы вы могли выполнять пространственные запросы к базе данных (альтернатива заключается в извлечении каждой записи из БД и запуске данных через PHP). MySQL предоставляет все математические функции, которые вам нужны.

Я сделал это для коммерческого веб-сайта, который предоставлял дистанционный поиск на основе почтовых индексов, поэтому это, безусловно, возможно без специальных функций ГИС.

0 голосов
/ 14 июня 2018

Только что наткнулся на эту тему. Может быть, кому-то будет интересна эта функция, протестированная в MySql 5.7:

    create function GetDistance(lat1 real, lng1 real, lat2 real, lng2 real) returns real no sql
    return ATAN2(SQRT(POW(COS(RADIANS(lat2)) * SIN(RADIANS(lng1 - lng2)), 2) + 
                POW(COS(RADIANS(lat1)) * SIN(RADIANS(lat2)) - SIN(RADIANS(lat1)) *
                COS(RADIANS(lat2)) *  COS(RADIANS(lng1 - lng2)), 2)), 
                (SIN(RADIANS(lat1)) * SIN(RADIANS(lat2)) + COS(RADIANS(lat1)) *
                COS(RADIANS(lat2)) * COS(RADIANS(lng1 - lng2)))) * 6372.795;

Призвание:

select GetDistance(your_latitude, your_longitude, table_field_lat,
                   table_field_lng) as dist from [your_table] limit 5;
0 голосов
/ 24 мая 2009

Почему вы не используете геопространственные функции MySQL ...? Нет, просто шучу.

Если 200 записей - это настоящие места, такие как города и т. Д., То в качестве альтернативы вы можете использовать API GeoNames?

Следующий веб-сервис предоставит 10 ближайших местоположений к предоставленной лат и лнг:

http://ws.geonames.org/findNearby?lat=47.3&lng=9

Источник: http://www.geonames.org/export/web-services.html#findNearbyPlaceName

Полный список: http://www.geonames.org/export/ws-overview.html

0 голосов
/ 21 мая 2009

MySQL имеет возможность индексировать строки геопространственно. Возможно, вам не нужно делать эту математику самостоятельно (вы можете просто попросить MySQL вычислить расстояние между двумя геообъектами и отсортировать по нему ..).

См .: http://forums.mysql.com/read.php?23,159205,159205

0 голосов
/ 21 мая 2009

Для этого есть функции MySQL.

http://dev.mysql.com/doc/refman/5.0/en/gis-introduction.html

...