Найти расстояние между двумя точками, используя широту и долготу в mysql

Привет У меня есть следующая таблица

 --------------------------------------------
 |  id  |  city  |  Latitude  |  Longitude  |
 --------------------------------------------
 |  1   |   3    |   34.44444 |   84.3434   |
 --------------------------------------------
 |  2   |   4    | 42.4666667 | 1.4666667   |
 --------------------------------------------
 |  3   |   5    |  32.534167 | 66.078056   |
 --------------------------------------------
 |  4   |   6    |  36.948889 | 66.328611   |
 --------------------------------------------
 |  5   |   7    |  35.088056 | 69.046389   |
 --------------------------------------------
 |  6   |   8    |  36.083056 |   69.0525   |
 --------------------------------------------
 |  7   |   9    |  31.015833 | 61.860278   |
 --------------------------------------------

Теперь я хочу получить расстояние между двумя точками. Скажите, что у пользователя есть город 3, а у пользователя есть город. 7. Мой сценарий - это один пользователь, имеющий город, латыт и долгота, ища других пользователей на расстоянии от своего города. Например, пользователь, имеющий город 3, ищет. Он хочет получить расстояние от пользователя любого другого города, скажем, что он равен 7. Я искал и нашел следующий запрос

SELECT `locations`.`city`, ( 3959 * acos ( cos ( radians(31.589167) ) * cos( radians( Latitude ) ) * cos( radians( Longitude ) - radians(64.363333) ) + sin ( radians(31.589167) ) * sin( radians( Latitude ) ) ) ) AS `distance` FROM `locations` HAVING (distance < 50)

Как известно, этот запрос находит расстояние от одной точки до всех других точек. Теперь я хочу получить расстояние от одной точки до другой точки.

Любая направляющая линия будет оценена по достоинству.

Ответ 1

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

Этот запрос сделает всю работу за вас, указав расстояние в км. Используется формула закона сферического косинуса.

Обратите внимание, что вы присоединяете таблицу к себе, чтобы вы могли получить две пары координат для вычисления.

SELECT a.city AS from_city, b.city AS to_city, 
   111.111 *
    DEGREES(ACOS(LEAST(1.0, COS(RADIANS(a.Latitude))
         * COS(RADIANS(b.Latitude))
         * COS(RADIANS(a.Longitude - b.Longitude))
         + SIN(RADIANS(a.Latitude))
         * SIN(RADIANS(b.Latitude))))) AS distance_in_km
  FROM city AS a
  JOIN city AS b ON a.id <> b.id
 WHERE a.city = 3 AND b.city = 7

Обратите внимание, что константа 111.1111 - это количество километров на градус широты, основанное на старом наполеоновском определении метра как одной десятитысячной расстояния от экватора до полюса. Это определение достаточно близко для определения местоположения.

Если вы хотите установить уставные мили вместо километров, используйте вместо этого 69.0.

http://sqlfiddle.com/#!2/abcc8/4/0

Если вы ищете ближайшие точки, у вас может возникнуть соблазн использовать что-то вроде этого:

   HAVING distance_in_km < 10.0    /* slow ! */
    ORDER BY distance_in_km DESC

То есть (как мы говорим, около Бостона, США), злой медленный.

В этом случае вам нужно использовать вычисление ограничивающего прямоangularьника. Посмотрите эту статью о том, как это сделать. http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/

Формула содержит функцию LEAST(). Почему? Поскольку функция ACOS() выдает ошибку, если ее аргумент даже немного больше 1. Когда две рассматриваемые точки очень близки друг к другу, выражение с вычислениями COS() и SIN() может иногда давать значение, немного большее, чем 1 из-за эпсилона с плавающей точкой (неточность). Вызов LEAST(1.0, dirty-great-expression) справляется с этой проблемой.

Есть лучший способ - формула formula от Таддеуса Винсенти. Он использует ATAN2(), а не ACOS(), поэтому он менее подвержен проблемам с эпсилонами.

Ответ 2

Вот запрос и функция MySQL, которые используют, чтобы получить расстояние между двумя широтой и долготой, и расстояние вернется в КМ.

Mysql Query: -

SELECT (6371 * acos( 
                cos( radians(lat2) ) 
              * cos( radians( lat1 ) ) 
              * cos( radians( lng1 ) - radians(lng2) ) 
              + sin( radians(lat2) ) 
              * sin( radians( lat1 ) )
                ) ) as distance from your_table

Mysql Функция: -

DELIMITER $$
CREATE FUNCTION 'getDistance'('lat1' VARCHAR(200), 'lng1' VARCHAR(200), 'lat2' VARCHAR(200), 'lng2' VARCHAR(200)) RETURNS varchar(10) CHARSET utf8
begin
declare distance varchar(10);

set distance = (select (6371 * acos( 
                cos( radians(lat2) ) 
              * cos( radians( lat1 ) ) 
              * cos( radians( lng1 ) - radians(lng2) ) 
              + sin( radians(lat2) ) 
              * sin( radians( lat1 ) )
                ) ) as distance); 

if(distance is null)
then
 return '';
else 
return distance;
end if;
end$$
DELIMITER ;

Как использовать в своем коде PHP

SELECT getDistance(lat1,lng1,$lat2,$lng2) as distance 
FROM your_table.

Ответ 3

Здесь функция MySQL, которая будет принимать две пары широта/долгота и давать вам расстояние в градусах между двумя точками. Он использует формулу Haversine для расчета расстояния. Поскольку Земля не является идеальной сферой, существует некоторая ошибка вблизи полюсов и экватора.

  • Чтобы преобразовать в мили, умножьте на 3961.
  • Чтобы перевести в километры, умножьте на 6373.
  • Чтобы преобразовать в метры, умножьте на 6373000.
  • Чтобы преобразовать в футы, умножьте на (3961 * 5280) 20914080.
DELIMITER $$

CREATE FUNCTION \'haversine\'(

        lat1 FLOAT, lon1 FLOAT,
        lat2 FLOAT, lon2 FLOAT
     ) RETURNS float
    NO SQL
    DETERMINISTIC
    COMMENT 'Returns the distance in degrees on the Earth between two known points of latitude and longitude. To get miles, multiply by 3961, and km by 6373'

BEGIN

    RETURN DEGREES(ACOS(
              COS(RADIANS(lat1)) *
              COS(RADIANS(lat2)) *
              COS(RADIANS(lon2) - RADIANS(lon1)) +
              SIN(RADIANS(lat1)) * SIN(RADIANS(lat2))
            ));

END;

DELIMITER;

Ответ 4

Не знаете, как выполняется расчет расстояний, но вам нужно сделать self join свою таблицу и выполнить расчет соответствующим образом. Что-то вроде этого возможно

select t1.id as userfrom, 
t2.id as userto, 
( 3959 * acos ( cos ( radians(31.589167) ) * cos( radians( t1.Latitude ) ) * 
cos( radians( t1.Longitude ) - radians(64.363333) ) + sin ( radians(31.589167) ) * 
sin( radians( t2.Latitude ) ) ) ) AS `distance` 
from table1 t1 
inner join table1 t2 on t2.city > t1.city

Ответ 5

Здесь формула, которую я преобразовал из https://www.geodatasource.com/developers/javascript

Это хорошая чистая функция, которая вычисляет расстояние в км

DELIMITER $$
CREATE DEFINER='root'@'localhost' FUNCTION 'FN_GET_DISTANCE'(
lat1 DOUBLE, lng1 DOUBLE, lat2 DOUBLE, lng2 DOUBLE
) RETURNS double
BEGIN
    DECLARE radlat1 DOUBLE;
    DECLARE radlat2 DOUBLE;
    DECLARE theta DOUBLE;
    DECLARE radtheta DOUBLE;
    DECLARE dist DOUBLE;
    SET radlat1 = PI() * lat1 / 180;
    SET radlat2 = PI() * lat2 / 180;
    SET theta = lng1 - lng2;
    SET radtheta = PI() * theta / 180;
    SET dist = sin(radlat1) * sin(radlat2) + cos(radlat1) * cos(radlat2) * cos(radtheta);
    SET dist = acos(dist);
    SET dist = dist * 180 / PI();
    SET dist = dist * 60 * 1.1515;
    SET dist = dist * 1.609344;
RETURN dist;
END$$
DELIMITER ;

На сайте вы также найдете одну и ту же функцию на разных языках;