2012-06-26 3 views
5

У меня возникают проблемы с попыткой вернуть ближайшее место пользователю через инструкцию SQL. Для тестирования я использую те же самые координаты, вот что у меня есть:Измерение расстояния между двумя точками Lat/Lng

SQL:

SELECT `companies`.`customerName` , 
    (3959 * 
     ACOS(
      COS(
       RADIANS(37.367485) * COS(RADIANS(`locations`.`gps_lat`)) * 
       COS(
        RADIANS(`locations`.`gps_lng`) - RADIANS(-77.399994) + 
        SIN(RADIANS(37.367485)) * SIN(RADIANS(`locations`.`gps_lat`)) 
       ) 
      ) 
     ) 
    ) 
AS `distance` 
FROM `locations` 
JOIN `companies` ON `locations`.`co_id` 
HAVING `distance` > 25 
ORDER BY distance 
LIMIT 0 , 10 

Результаты:

| customerName | distance   | 
| SOME COMPANY | 1914.41747964854 | 


locationsтаблице значений :

gps_lat | gps_lng 
37.367485 | -77.399994 


Я использовал пример из Google, я проверил формулу несколько раз, и я не могу придумать, куда я пошел неправильно. Любая помощь приветствуется.


EDIT:
Поскольку, как представляется, некоторая путаница на меня, зная, что я делаю:

> был заменен, чтобы получить результат, 1914, очевидно, больше чем 25.

Приложение это передача координат пользователей из приложения для Android на наш веб-сервер. Широта и долгота будут вытягиваться из значений $_GET и перекрестно привязаны от компаний в нашей базе данных MYSQL веб-серверов.

Синтаксис выше - это просто проверка моего оператора SQL в Mysql Workbench. Очевидно, что я ищу результат с нулевым значением.

+3

Если вы хотите ближе, почему бы ограничить его на «расстояние > 25 "? –

+0

Я сделал, вернул нулевые результаты. Обратите внимание на расстояние, которое оно дало мне выше – jnthnjns

+2

В зависимости от того, какую СУБД вы используете, могут быть значительно упрощены (и быстрее) способы сделать это. Пример: [MySQL] (http://dev.mysql.com/doc/refman/5.0/en/spatial-extensions.html), [SQL Server] (http://msdn.microsoft.com/en-us/ библиотека/bb933876% 28v = sql.105% 29.aspx), [PostgreSQL] (http://postgis.refractions.net/). –

ответ

5

Я думаю, что я решил эту проблему, перейдя от примера Гуглса к формуле, предоставленной «Приключениями принятого йопера». Использование его/ее версии Haversine Formula.
Примечание. Пример Google, приведенный выше, также использует Haversine.

SQL:

SELECT `companies`.`customerName` , 
(2 * (3959 * ATAN2(
      SQRT(
      POWER(SIN((RADIANS(37.367485 - `locations`.`gps_lat`))/2), 2) + 
      COS(RADIANS(`locations`.`gps_lat`)) * 
      COS(RADIANS(37.367485)) * 
      POWER(SIN((RADIANS(-77.399994 - `locations`.`gps_lng`))/2), 2) 
     ), 
      SQRT(1-(
      POWER(SIN((RADIANS(37.367485 - `locations`.`gps_lat`))/2), 2) + 
      COS(RADIANS(`locations`.`gps_lat`)) * 
      COS(RADIANS(37.367485)) * 
      POWER(SIN((RADIANS(-77.399994 - `locations`.`gps_lng`))/2), 2) 
     )) 
     ) 
    )) 
AS 'distance' 
FROM `locations` 
JOIN `companies` ON `locations`.`co_id` 
HAVING distance < 25 
ORDER BY distance 
LIMIT 0 , 10 



Для тех, кому интересно на моем приложении, Final PHP:

GET Значение: ?lat=37.367485&lng=-77.399994

$earth_radius_miles = 3959; // Earth radius in miles 
$earth_radius_kilometers = 6371; // Earth radius in kilometers 
$result_radius = 10000; // Maximum distance in either miles or kilometers 

$get_lat = $_GET["lat"]; 
$get_lng = $_GET["lng"]; 

$dbSelect = mysql_query("SELECT `companies`.`customerName`, 
(2 * (".$earth_radius_miles." * ATAN2(
      SQRT(
      POWER(SIN((RADIANS(".$get_lat." - `locations`.`gps_lat`))/2), 2) + 
      COS(RADIANS(`locations`.`gps_lat`)) * 
      COS(RADIANS(".$get_lat.")) * 
      POWER(SIN((RADIANS(".$get_lng." - `locations`.`gps_lng`))/2), 2) 
     ), 
      SQRT(1-(
      POWER(SIN((RADIANS(".$get_lat." - `locations`.`gps_lat`))/2), 2) + 
      COS(RADIANS(`locations`.`gps_lat`)) * 
      COS(RADIANS(".$get_lat.")) * 
      POWER(SIN((RADIANS(".$get_lng." - `locations`.`gps_lng`))/2), 2) 
     )) 
     ) 
    )) 
AS 'distance' 
FROM `locations` 
JOIN `companies` ON `locations`.`co_id` 
HAVING distance < ".$result_radius." 
ORDER BY distance 
LIMIT 0 , 10") 
or die(mysql_error()); 

Результаты:

[{"customerName":"SOME COMPANY","distance":"0"}] 

Я протестированные эти результаты с другими координатами и, кажется, работает отлично.Не тестировали ничего с большим расстоянием между двумя точками, но мое приложение не требует от меня этого.

+1

Невозможно подтвердить, но +1 для представления – Smandoli

1

Ashok, вы можете рассчитать расстояние между двумя cordinates, используя следующую формулу:

enter image description here

где

R = radius of the earth (6,371 km) 
Δlat = |lat2- lat1| 
Δlong = |long2- long1| 
Смежные вопросы