두 위도 / 경도 사이의 거리를 찾는 가장 빠른 방법


227

현재 경도와 위도 정보가있는 mysql 데이터베이스의 위치가 백만 개 미만입니다.

쿼리를 통해 한 점과 다른 점 사이의 거리를 찾으려고합니다. 특히 초당 100 회 이상 히트하는 것만 큼 빠르지는 않습니다.

이것에 대해 mysql 이외의 빠른 쿼리 또는 더 빠른 시스템이 있습니까? 이 쿼리를 사용하고 있습니다 :

SELECT 
  name, 
   ( 3959 * acos( cos( radians(42.290763) ) * cos( radians( locations.lat ) ) 
   * cos( radians(locations.lng) - radians(-71.35368)) + sin(radians(42.290763)) 
   * sin( radians(locations.lat)))) AS distance 
FROM locations 
WHERE active = 1 
HAVING distance < 10 
ORDER BY distance;

참고 : 제공되는 거리는 마일 입니다. 킬로미터 가 필요한 경우 6371대신을 사용하십시오 3959.


31
당신이주는 공식은 일정한 많은 요소를 가지고있는 것 같습니다. 데이터를 사전 계산하고 해당 값을 DB에 저장할 수 있습니까? 예를 들어 3959 * acos (cos (radians (42.290763))는 상수이지만 4 개의 주요 계산이 있습니다. 대신 6696.7837을 저장할 수 있습니까?
Peter M

1
아니면 쿼리 외부에서 적어도 사전 계산 상수? 그렇게해야 할 일이 줄어 듭니다.
Peter M

2
@Peter M 괜찮은 SQL 데이터베이스가 한 번만 계산되도록 최적화하는 것 같습니다.
mhenry1384

25
궁금한 점이있는 경우 42.290763은 위도이고 -71.35368은 거리를 계산할 지점의 경도입니다.
user276648

14
정보를 위해,이 공식에 의해 caluclated 거리는 킬로미터가 아닌 마일입니다 .3959를 6371로 대체하여 킬로미터 단위로 결과를 얻으십시오
Sahil

답변:


115
  • 표의 데이터 유형 Point값을 사용하여 포인트를 작성하십시오 . Mysql 5.7.5 부터는 이제 테이블도 인덱스 를 지원 합니다.GeometryMyISAMInnoDBSPATIAL

  • SPATIAL이 점에 대한 색인을 작성하십시오

  • MBRContains()값을 찾는 데 사용하십시오 .

    SELECT  *
    FROM    table
    WHERE   MBRContains(LineFromText(CONCAT(
            '('
            , @lon + 10 / ( 111.1 / cos(RADIANS(@lon)))
            , ' '
            , @lat + 10 / 111.1
            , ','
            , @lon - 10 / ( 111.1 / cos(RADIANS(@lat)))
            , ' '
            , @lat - 10 / 111.1 
            , ')' )
            ,mypoint)

또는 MySQL 5.1이상 :

    SELECT  *
    FROM    table
    WHERE   MBRContains
                    (
                    LineString
                            (
                            Point (
                                    @lon + 10 / ( 111.1 / COS(RADIANS(@lat))),
                                    @lat + 10 / 111.1
                                  ),
                            Point (
                                    @lon - 10 / ( 111.1 / COS(RADIANS(@lat))),
                                    @lat - 10 / 111.1
                                  ) 
                            ),
                    mypoint
                    )

상자 안에있는 모든 지점을 선택합니다 (@lat +/- 10 km, @lon +/- 10km).

이것은 실제로 상자가 아니라 구형 사각형입니다 : 구의 위도와 경도 경계 세그먼트. 이것은 프란츠 조셉 랜드 (Franz Joseph Land) 의 평범한 사각형과 다를 수 있지만, 대부분의 거주 지역의 사각형과 매우 비슷합니다.

  • 추가 필터링을 적용하여 원 안의 모든 것을 선택하십시오 (사각형 아님)

  • 원거리가 큰 경우 (원거리의 경우) 추가 미세 필터링을 적용 할 수 있습니다.


15
@Quassnoi : 몇 가지 수정 : 좌표 순서를 위도, 경도로 전환하고 싶을 것입니다. 또한 세로 거리는 경도 가 아닌 위도 의 코사인에 비례합니다 . 그리고 당신은 당신이 처음으로 수정 될 좌표, 그래서 부문에 곱셈에서 변경 할 수 있습니다 @lon - 10 / ( 111.1 / cos(@lat))모든 것이 정확하면 한 쌍에서 두 번째 (그리고합니다.
M. 데이브 Auayan에게

8
경고 : 답변 본문은 @M이 작성한 매우 유효한 설명에 따라 편집되지 않았습니다. 데이브 아우 얀. 추가 참고 사항 : 관심있는 원이 극을 포함하거나 (b) 경도의 +/- 180도 자오선과 교차하는 경우이 방법은 배 모양이됩니다. 또한 cos(lon)작은 거리에서만 정확합니다. janmatuschek.de/LatitudeLongitudeBoundingCoordinates
John Machin

3
상수 (10, 111.11, @lat, @lon, mypoint)가 나타내는 내용에 대한 통찰력을 얻을 수있는 방법이 있습니까? 10은 킬로미터 거리에 대한 것으로 가정하고 @lat 및 @lon은 제공된 위도 및 경도를 나타내지 만 111.11 및 mypoint는 예제에서 무엇을 나타 냅니까?
ashays 2016 년

4
@ashays : 111.(1)위도 는 대략 km입니다. mypoint좌표를 저장하는 테이블의 필드입니다.
Quassnoi 2016 년

1
또 다른 오류 수정 - 당신은 마지막 줄에 두 번째의 폐쇄) 누락
인애

100

MySql 전용 답변은 아니지만 SQL 문의 성능을 향상시킵니다.

효과적으로하는 것은 테이블의 모든 지점까지의 거리를 계산하여 주어진 지점의 10 단위 내에 있는지 확인하는 것입니다.

이 SQL을 실행하기 전에 할 수있는 일은 포인트가 중앙에있는 측면에 20 단위의 상자를 그리는 4 개의 포인트를 만드는 것입니다. (x1, y1). . . (x4, y4), 여기서 (x1, y1)은 (Lat + 10 단위로 주어진 +10 단위)입니다. . . (주문 된 -10 단위, 주어진 -10 단위). 실제로, 당신은 두 개의 포인트 만 필요합니다. 왼쪽 상단과 오른쪽 하단은 (X1, Y1)과 (X2, Y2)

이제 SQL 문은 이러한 점을 사용하여 주어진 점에서 확실히 10u 이상인 행을 제외하고 위도 및 경도에 대한 인덱스를 사용할 수 있으므로 현재보다 훨씬 빠릅니다.

예 :

select . . . 
where locations.lat between X1 and X2 
and   locations.Long between y1 and y2;

상자 접근 방식은 오 탐지를 반환 할 수 있으므로 (상자의 모서리에서 주어진 점에서 10u보다 큰 점을 선택할 수 있음) 여전히 각 점의 거리를 계산해야합니다. 그러나 테스트 할 포인트의 수를 상자 안의 포인트로 대폭 제한했기 때문에 이것은 다시 훨씬 빠릅니다.

이 기술을 "상자 안에서 생각하기"라고 부릅니다. :)

편집 : 이것은 하나의 SQL 문에 넣을 수 있습니까?

mySql 또는 Php의 기능이 무엇인지 잘 모르겠습니다. 죄송합니다. 가장 좋은 장소가 4 점을 구축하는 방법 또는 Php의 mySql 쿼리에 전달할 수있는 방법을 모르겠습니다. 그러나 일단 네 가지 점이 있으면 자신의 SQL 문과 광산을 결합하는 것을 막을 수 있습니다.

select name, 
       ( 3959 * acos( cos( radians(42.290763) ) 
              * cos( radians( locations.lat ) ) 
              * cos( radians( locations.lng ) - radians(-71.35368) ) 
              + sin( radians(42.290763) ) 
              * sin( radians( locations.lat ) ) ) ) AS distance 
from locations 
where active = 1 
and locations.lat between X1 and X2 
and locations.Long between y1 and y2
having distance < 10 ORDER BY distance;

MS SQL을 사용하면 4 개의 float (X1, Y1, X2, Y2)을 선언하고 "main"select 문 전에 계산하는 SQL 문을 작성할 수 있습니다. MySql. 그러나 나는 여전히 C #에서 4 개의 지점을 작성하고 매개 변수로 SQL 쿼리에 전달하는 경향이 있습니다.

누군가가 MySQL & Php의 특정 부분에 대답 할 수 있다면 더 도움이 될 수 없습니다.이 답변을 자유롭게 편집하십시오.


4
이 프리젠 테이션에서이 접근법에 대한 mysql 프로 시저를 찾을 수 있습니다. scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL
Lucia

37
6371.로 3959을 대체하는 대신 마일 킬로미터 검색하려면
ErichBSchulz

4
+1, 훌륭한 옵션; 상자를 추가하면 검색어가 평균 4 초에서 0.03 초로 줄었습니다.
jvenema

1
너무 논리적 인 것처럼 보이지만이 솔루션에 대한 상을 보유하고 있습니다! 2 개의 레코드 레코드 데이터베이스에서 쿼리는 16 초에서 0.06 초로 이동했습니다. 참고 : 쿼리에서 거리 계산을 잘라 내고 프로그램 코드에서 거리를 계산하면 훨씬 빠릅니다 (큰 테이블의 경우).
NLAnaconda

2
@Binary Worrier : X1, X2 및 Y1, Y2는 여기에 주어진 예제에 따라 경도 최소 및 최대 및 위도 최소 및 최대가됩니다 : blog.fedecarg.com/2009/02/08/… 조언하십시오.
Prabhat

14

다음 MySQL 함수 가이 블로그 게시물에 게시되었습니다 . 나는 그것을 많이 테스트하지는 않았지만, 게시물에서 수집 한 것에서 위도 및 경도 필드가 색인 되어 있으면 이것이 잘 작동 할 수 있습니다.

DELIMITER $$

DROP FUNCTION IF EXISTS `get_distance_in_miles_between_geo_locations` $$
CREATE FUNCTION get_distance_in_miles_between_geo_locations(
  geo1_latitude decimal(10,6), geo1_longitude decimal(10,6), 
  geo2_latitude decimal(10,6), geo2_longitude decimal(10,6)) 
returns decimal(10,3) DETERMINISTIC
BEGIN
  return ((ACOS(SIN(geo1_latitude * PI() / 180) * SIN(geo2_latitude * PI() / 180) 
    + COS(geo1_latitude * PI() / 180) * COS(geo2_latitude * PI() / 180) 
    * COS((geo1_longitude - geo2_longitude) * PI() / 180)) * 180 / PI()) 
    * 60 * 1.1515);
END $$

DELIMITER ;

샘플 사용법 :

& places필드로 불리는 테이블을 가정 :latitudelongitude

SELECT get_distance_in_miles_between_geo_locations(-34.017330, 22.809500,
latitude, longitude) AS distance_from_input FROM places;

나는 이것을 시도했지만 완벽하게 작동하지만 어쨌든 distance_from_input을 기반으로 WHERE 문을 넣을 수는 없습니다. 왜 안 되 겠어요?
Chris Visser

하위 선택으로 할 수 있습니다. select * from (...) as t where distance_from_input> 5;
Brad Parks

2
또는 그냥 똑바로 가십시오 : get_distance_in_miles_between_geo_locations (-34.017330, 22.809500, 위도, 경도)> 5000;
Brad Parks

2
리턴 미터 :SELECT ROUND(((ACOS(SIN(lat1 * PI() / 180) * SIN(lat2 * PI() / 180) + COS(lat1 * PI() / 180) * COS(lat2 * PI() / 180) * COS((lnt1 - lnt2) * PI() / 180)) * 180 / PI()) * 60 * 1.1515) * 1.609344 * 1000) AS distance
모하마드

13

비슷한 문제 (단일 지점에서 거리로 행을 필터링)를 해결하고 원래의 질문과 답변 및 의견을 결합하여 MySQL 5.6 및 5.7에서 완벽하게 작동하는 솔루션을 생각해 냈습니다.

SELECT 
    *,
    (6371 * ACOS(COS(RADIANS(56.946285)) * COS(RADIANS(Y(coordinates))) 
    * COS(RADIANS(X(coordinates)) - RADIANS(24.105078)) + SIN(RADIANS(56.946285))
    * SIN(RADIANS(Y(coordinates))))) AS distance
FROM places
WHERE MBRContains
    (
    LineString
        (
        Point (
            24.105078 + 15 / (111.320 * COS(RADIANS(56.946285))),
            56.946285 + 15 / 111.133
        ),
        Point (
            24.105078 - 15 / (111.320 * COS(RADIANS(56.946285))),
            56.946285 - 15 / 111.133
        )
    ),
    coordinates
    )
HAVING distance < 15
ORDER By distance

coordinates유형이있는 필드 POINT이고 SPATIAL색인
6371이 거리 (킬로미터)를 계산
56.946285하기위한 것입니다. 중심점의 위도입니다. 중심점의
24.105078경도
15는 킬로미터입니다

필자의 테스트에서 MySQL은 SPATIAL index on coordinatesfield를 사용하여 직사각형 내에있는 모든 행을 신속하게 선택한 다음 모든 필터링 된 장소에 대한 실제 거리를 계산하여 사각형 모서리에서 장소를 제외하고 원 안에 자리를 남겨 둡니다.

이것은 내 결과의 시각화입니다.

지도

회색 별은지도의 모든 지점을 시각화하고 노란색 별은 MySQL 쿼리에서 반환되는 별입니다. 사각형의 모서리 내부 (그러나 바깥 쪽 원)에있는 회색 별 MBRContains()HAVING절에 의해 선택되었다가 선택 해제되었습니다 .


이것을 충분히 찬성 할 수 없습니다. 약 5 백만 개의 레코드가있는 테이블과이 방법으로 공간 인덱스를 검색하면 검색 시간은 기존 A8 프로세서에서 0.005 초입니다. 6371을 3959로 대체하여 마일리지로 결과를 얻을 수 있지만 111.133 및 111.320의 값을 조정해야합니까 아니면 보편적으로 일정합니까?
Wranorn

훌륭한 솔루션.
SeaBiscuit

Point를 만드는 방법은 POINT (lat, lng) 또는 POINT (lng, lat)입니다.
user606669

2
@ user606669 POINT (lng, lat)
Māris Kiseļovs

요즘 X () 및 Y () 함수는 ST_Y 및 ST_X 여야합니다.
안드레아스

11

MySQL 5.7. *를 사용하는 경우 st_distance_sphere (POINT, POINT)를 사용할 수 있습니다 .

Select st_distance_sphere(POINT(-2.997065, 53.404146 ), POINT(58.615349, 23.56676 ))/1000  as distcance

1
이것은 매우 좋고 읽기 쉬운 대안입니다. POINT ()에 대한 매개 변수 순서는 (lng, lat)입니다. 그렇지 않으면 "close"로 끝날 수 있지만 여기서는 다른 방법과는 매우 다른 결과를 얻을 수 있습니다. 참조 : stackoverflow.com/questions/35939853/...
앤디 P

9
SELECT * FROM (SELECT *,(((acos(sin((43.6980168*pi()/180)) * 
sin((latitude*pi()/180))+cos((43.6980168*pi()/180)) * 
cos((latitude*pi()/180)) * cos(((7.266903899999988- longitude)* 
pi()/180))))*180/pi())*60*1.1515 ) as distance 
FROM wp_users WHERE 1 GROUP BY ID limit 0,10) as X 
ORDER BY ID DESC

이것은 MySQL의 포인트 사이의 거리 계산 쿼리이며 긴 데이터베이스에서 사용했으며 완벽하게 작동합니다! 참고 : 요구 사항에 따라 변경 (데이터베이스 이름, 테이블 이름, 열 등)을 수행하십시오.


1.1515 값은 무엇을 나타 냅니까? 전에도 비슷한 공식을 보았지만 1.1515 대신 1.75를 사용했습니다.
TryHarder

1
내 자신의 질문에 대한 답변으로, 여기에 대답이있을 것이라고 생각합니다. stackoverflow.com/a/389251/691053
TryHarder

8
set @latitude=53.754842;
set @longitude=-2.708077;
set @radius=20;

set @lng_min = @longitude - @radius/abs(cos(radians(@latitude))*69);
set @lng_max = @longitude + @radius/abs(cos(radians(@latitude))*69);
set @lat_min = @latitude - (@radius/69);
set @lat_max = @latitude + (@radius/69);

SELECT * FROM postcode
WHERE (longitude BETWEEN @lng_min AND @lng_max)
AND (latitude BETWEEN @lat_min and @lat_max);

출처


11
출처를 인용하십시오. 이 글은 : blog.fedecarg.com/2009/02/08/…
redburn

이 경우 69는 무엇입니까? 지구 반경이있는 경우 어떻게해야합니까?
CodeRunner

2
1 위도의 킬로미터는 111 KM입니다. 1 위도의 마일은 69 마일입니다. 그리고 69 마일 = 111 KM. 이것이 전환에서 매개 변수를 사용한 이유입니다.
CodeRunner

나는 이것을 영원히 찾고 있었다. 그것이 그렇게 간단 할 수 있다는 것을 몰랐습니다. 정말 고맙습니다.
Vikas

lng_min / lng_max가 반경 계산에서 lat_min 및 lat_max를 사용해야하므로 이것이 올바르지 않습니까?
Ben

6
   select
   (((acos(sin(('$latitude'*pi()/180)) * sin((`lat`*pi()/180))+cos(('$latitude'*pi()/180)) 
    * cos((`lat`*pi()/180)) * cos((('$longitude'- `lng`)*pi()/180))))*180/pi())*60*1.1515) 
    AS distance
    from table having distance<22;

5

두 좌표 사이의 미터 수를 반환하는 MySQL 함수 :

CREATE FUNCTION DISTANCE_BETWEEN (lat1 DOUBLE, lon1 DOUBLE, lat2 DOUBLE, lon2 DOUBLE)
RETURNS DOUBLE DETERMINISTIC
RETURN ACOS( SIN(lat1*PI()/180)*SIN(lat2*PI()/180) + COS(lat1*PI()/180)*COS(lat2*PI()/180)*COS(lon2*PI()/180-lon1*PI()/180) ) * 6371000

다른 형식으로 값을 반환하려면 6371000선택한 단위에서 함수의을 지구 반경으로 바꿉니다. 예를 들어, 킬로미터는 6371및 마일은입니다 3959.

함수를 사용하려면 MySQL의 다른 함수와 마찬가지로 호출하십시오. 예를 들어 table이 있으면 city모든 도시와 다른 도시 사이의 거리를 찾을 수 있습니다.

SELECT
    `city1`.`name`,
    `city2`.`name`,
    ROUND(DISTANCE_BETWEEN(`city1`.`latitude`, `city1`.`longitude`, `city2`.`latitude`, `city2`.`longitude`)) AS `distance`
FROM
    `city` AS `city1`
JOIN
    `city` AS `city2`

4

MySQL 플러그인으로 설치하는 방법에 대한 자세한 내용은 https://github.com/lucasepe/lib_mysqludf_haversine을 참조 하십시오.

나는 작년에 의견으로 게시했습니다. @TylerCollier가 친절하게 답변으로 게시하도록 제안 했으므로 여기에 있습니다.

또 다른 방법은 두 점에서 haversine 거리를 반환하는 사용자 지정 UDF 함수를 작성하는 것입니다. 이 함수는 입력을받을 수 있습니다.

lat1 (real), lng1 (real), lat2 (real), lng2 (real), type (string - optinal - 'km', 'ft', 'mi')

따라서 다음과 같이 작성할 수 있습니다.

SELECT id, name FROM MY_PLACES WHERE haversine_distance(lat1, lng1, lat2, lng2) < 40;

40km 미만의 거리를 가진 모든 레코드를 가져옵니다. 또는:

SELECT id, name FROM MY_PLACES WHERE haversine_distance(lat1, lng1, lat2, lng2, 'ft') < 25;

25 피트 미만의 거리를 가진 모든 레코드를 가져옵니다.

핵심 기능은 다음과 같습니다.

double
haversine_distance( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ) {
    double result = *(double*) initid->ptr;
    /*Earth Radius in Kilometers.*/ 
    double R = 6372.797560856;
    double DEG_TO_RAD = M_PI/180.0;
    double RAD_TO_DEG = 180.0/M_PI;
    double lat1 = *(double*) args->args[0];
    double lon1 = *(double*) args->args[1];
    double lat2 = *(double*) args->args[2];
    double lon2 = *(double*) args->args[3];
    double dlon = (lon2 - lon1) * DEG_TO_RAD;
    double dlat = (lat2 - lat1) * DEG_TO_RAD;
    double a = pow(sin(dlat * 0.5),2) + 
        cos(lat1*DEG_TO_RAD) * cos(lat2*DEG_TO_RAD) * pow(sin(dlon * 0.5),2);
    double c = 2.0 * atan2(sqrt(a), sqrt(1-a));
    result = ( R * c );
    /*
     * If we have a 5th distance type argument...
     */
    if (args->arg_count == 5) {
        str_to_lowercase(args->args[4]);
        if (strcmp(args->args[4], "ft") == 0) result *= 3280.8399;
        if (strcmp(args->args[4], "mi") == 0) result *= 0.621371192;
    }

    return result;
}

3

구형 투영으로 빠르고 간단하며 정확한 (더 작은 거리의) 근사를 수행 할 수 있습니다 . 적어도 내 라우팅 알고리즘에서 올바른 계산에 비해 20 % 향상됩니다. Java 코드에서는 다음과 같습니다.

public double approxDistKm(double fromLat, double fromLon, double toLat, double toLon) {
    double dLat = Math.toRadians(toLat - fromLat);
    double dLon = Math.toRadians(toLon - fromLon);
    double tmp = Math.cos(Math.toRadians((fromLat + toLat) / 2)) * dLon;
    double d = dLat * dLat + tmp * tmp;
    return R * Math.sqrt(d);
}

MySQL에 대해 잘 모르겠습니다 (죄송합니다).

한계에 대해 알고 있어야합니다 (assertEquals의 세 번째 매개 변수는 킬로미터 단위의 정확도를 의미 함).

    float lat = 24.235f;
    float lon = 47.234f;
    CalcDistance dist = new CalcDistance();
    double res = 15.051;
    assertEquals(res, dist.calcDistKm(lat, lon, lat - 0.1, lon + 0.1), 1e-3);
    assertEquals(res, dist.approxDistKm(lat, lon, lat - 0.1, lon + 0.1), 1e-3);

    res = 150.748;
    assertEquals(res, dist.calcDistKm(lat, lon, lat - 1, lon + 1), 1e-3);
    assertEquals(res, dist.approxDistKm(lat, lon, lat - 1, lon + 1), 1e-2);

    res = 1527.919;
    assertEquals(res, dist.calcDistKm(lat, lon, lat - 10, lon + 10), 1e-3);
    assertEquals(res, dist.approxDistKm(lat, lon, lat - 10, lon + 10), 10);


3

MySQL 을 이용한 Geo Distance Search에 대해 읽어보기Haversine Formula to MySQL의 구현을 기반으로하는 솔루션 인 . 이론, 구현 및 추가 성능 최적화가 포함 된 완벽한 솔루션 설명입니다. 내 경우에는 공간 최적화 부분이 제대로 작동하지 않았지만.

나는 이것에서 두 가지 실수를 발견했다.

  1. 의 사용 absP8에 select 문이다. 방금 생략 abs했고 효과가있었습니다.

  2. p27의 공간 검색 거리 함수는 cos(latitude)공간 데이터를 고려하여로드하지 않는 한 ( 라디안으로 라디안 또는 곱하기 경도로 변환하지 않음 ), p26의 그의 예는 그의 공간 데이터 POINT가로드되지 않았 음을 나타냅니다. 라디안 또는도.


0
$objectQuery = "SELECT table_master.*, ((acos(sin((" . $latitude . "*pi()/180)) * sin((`latitude`*pi()/180))+cos((" . $latitude . "*pi()/180)) * cos((`latitude`*pi()/180)) * cos(((" . $longitude . "- `longtude`)* pi()/180))))*180/pi())*60*1.1515  as distance FROM `table_post_broadcasts` JOIN table_master ON table_post_broadcasts.master_id = table_master.id WHERE table_master.type_of_post ='type' HAVING distance <='" . $Radius . "' ORDER BY distance asc";

0

mysql 사용

SET @orig_lon = 1.027125;
SET @dest_lon = 1.027125;

SET @orig_lat = 2.398441;
SET @dest_lat = 2.398441;

SET @kmormiles = 6371;-- for distance in miles set to : 3956

SELECT @kmormiles * ACOS(LEAST(COS(RADIANS(@orig_lat)) * 
 COS(RADIANS(@dest_lat)) * COS(RADIANS(@orig_lon - @dest_lon)) + 
 SIN(RADIANS(@orig_lat)) * SIN(RADIANS(@dest_lat)),1.0)) as distance;

참조 : https://andrew.hedges.name/experiments/haversine/

참조 : https://stackoverflow.com/a/24372831/5155484

참조 : http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/

참고 : https://stackoverflow.com/a/24372831/5155484에LEAST 제안 된 의견으로 null 값을 피하는 데 사용됩니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.