오라클: 좌표 lat, lng 거리 계산

오라클에서 SQL로 좌표간 거리 계산 수식

위도, 경도에 의한 좌표체계는 WGS84를 말한다.
지구가 둥글다는 것을 감안했기 때문에 지구 반지름을 감안해 거리를 계산한다.
(따라서 어느 정도는 부정확한 점을 감수해야 함)

  • 위도: lat ==> Y좌표
  • 경도: lng ==> X좌표

기준점: 삼성혈 (lat=33.504274, lng=126.529182)

네이버 지도: ‘삼성혈’을 기준으로 ‘제주국제여객터미널’과 ‘노형우체국’과의 거리
캡처-네이버_지도-거리계산_비교

좌표로 계산된 거리: ‘삼성혈’을 기준으로 ‘제주국제여객터미널’과 ‘노형우체국’과의 거리
캡처-오라클_쿼리-거리계산_삼성혈기준

** 참고문서
MySQL의 좌표 계산식

오라클에는 radians 함수가 지원되지 않아 만들어야 한다.
수식도 함께 있으니 참고할 것
Oracle circle distance search: missing results

SELECT (( ACOS(
SIN($latitude * PI() / 180) * SIN(Latitude * PI() / 180) + COS($latitude * PI() / 180) * COS(Latitude * PI() / 180) * COS(($longitude - Longitude) * PI() / 180)) * 180 / PI()) * 60 * 1.1515) AS `distance` FROM `table_name`

이건 우리나라 블로그에서 사용된 계산법이다.

여기에 첨언을 더 하자면, 계산식 보다는 계산 범위를 줄이는 것이 우선이다.
우선 2km 범위를 탐색하는 것이 목적이라면, 좌표값으로 대충 이런 범위를 갖더라.

  • -0.019 ~ lat(위도) ~ +0.019
  • -0.022 ~ lng(경도) ~ +0.022

CREATE OR REPLACE FUNCTION RADIANS(nDegrees IN NUMBER) 
RETURN NUMBER DETERMINISTIC 
IS
BEGIN
  /*
  -- radians = degrees / (180 / pi)
  -- RETURN nDegrees / (180 / ACOS(-1)); but 180/pi is a constant, so...
  */
  RETURN nDegrees / 57.29577951308232087679815481410517033235;
END RADIANS;

create or replace function DISTNACE_WGS84( H_LAT in number, H_LNG in number, T_LAT in number, T_LNG in number)
return number deterministic
is
begin
  return ( 6371.0 * acos(  
          cos( radians( H_LAT ) )*cos( radians( T_LAT /* 위도 */ ) )
          *cos( radians( T_LNG /* 경도 */ )-radians( H_LNG ) )
          +
          sin( radians( H_LAT ) )*sin( radians( T_LAT /* 위도 */ ) )        
         ));
end DISTNACE_WGS84;

select DISTNACE_WGS84(33.504274, 126.529182, 33.524383, 126.544333) from dual;
/* 결과 2.64059773979495999846417249534463003211 */

/*
  삼성혈 LOCALY = 33.504274, LOCALX = 126.529182
*/
select * from (
select STATIONID, STATIONNM, LOCALY, LOCALX
    , DISTNACE_WGS84(33.504274, 126.529182, LOCALY, LOCALX) as DISTANCE
from DEV_BIS_STATION
where (LOCALY between 33.504274-0.019 and 33.504274+0.019)
    and (LOCALX between 126.529182-0.022 and 126.529182+0.022)
order by DISTANCE) TMP where rownum < 10;

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

%s에 연결하는 중

%d 블로거가 이것을 좋아합니다: