오라클에서 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;