MySQL을 사용하여 멀리 떨어진 지점 찾기


20

사용자 이름, 위도 및 경도가있는 mySQL 테이블이 있습니다. 주어진 거리와 주어진 위도와 경도의 원이나 사각형 안에있는 사용자 목록을 얻고 싶습니다. 예를 들어 내 입력 Lat = 78.3232 및 Long = 65.3234 및 거리 = 30 마일입니다. 78.3232 및 65.3234 지점에서 30 마일 이내에있는 사용자 목록을 얻고 싶습니다. 단일 쿼리 로이 문제를 해결할 수 있습니까? 아니면이 쿼리를 해결하기위한 힌트를 줄 수 있습니까? 지역 기반 정보를 처음 사용합니다.


왜 PostGIS가 아닌가? 지리 프로젝트를 시작하는 경우에도 스택을 변경할 수 있습니다
simplexio

stackoverflow.com/a/40272394/1281385 이 쿼리 속도를 높이는 데 유용해야합니다 (필요한 경우)
exussum

답변:


32

78.3232, 65.3234 좌표에서 반경 30 마일 내에있는 가장 가까운 20 개의 위치를 ​​찾는 SQL 문입니다. 해당 행의 위도 / 경도 및 대상 위도 / 경도를 기반으로 거리를 계산 한 다음 거리 값이 30 마일 미만인 행만 요청하고 전체 쿼리를 거리별로 정렬하여 20 개의 결과로 제한합니다. 마일 대신 킬로미터로 검색하려면 3959를 6371로 바꾸십시오.

SELECT
  id, (
    3959 * acos (
      cos ( radians(78.3232) )
      * cos( radians( lat ) )
      * cos( radians( lng ) - radians(65.3234) )
      + sin ( radians(78.3232) )
      * sin( radians( lat ) )
    )
  ) AS distance
FROM markers
HAVING distance < 30
ORDER BY distance
LIMIT 0 , 20;

이미 보유한 MySQL 백엔드와 함께 Google Maps API v3을 사용하고 있습니다.

https://developers.google.com/maps/articles/phpsqlsearch_v3#findnearsql


"#
1582-

발견 : lng 변수가 비어있었습니다! 죄송합니다!
bluantinoo

정확히 내가 원하는 것이지만 수천 개의 레코드에 대한 쿼리 성능 과부하는 무엇입니까? 정확도는 어떻습니까?
Amit Shah

1
미터로 검색하기 위해 6371392.896로 대체하는 것이 훨씬 좋습니다
Vasilii Suricov

34

Mapperz의 답변 이 잘못되었습니다. 부비동은 위도가 아닌 경도에서 계산되어야합니다. 따라서 간결한 SQL 문은 다음과 같습니다.

SELECT
    id, (
      3959 * acos (
      cos ( radians(78.3232) )
      * cos( radians( lat ) )
      * cos( radians( lng ) - radians(65.3234) )
      + sin ( radians(78.3232) )
      * sin( radians( lat ) )
    )
) AS distance
FROM markers
HAVING distance < 30
ORDER BY distance
LIMIT 0 , 20;

답은 1 일로 주문해야합니다.
Amit Shah

@AmitShah 당신은 당신이 및 / 또는 투표를 (거의 육년의 사이트에서 활성화되지 않았습니다 @shihabK) 아스 커를 ping 수 있다고 생각한다면 meta.stackexchange.com/questions/268666/...
PolyGeo

이것이 정답입니다.
catbadger

2

함수를 만드는 데 기본이 될 수 있습니다 .. 다른 영역에서 재사용 할 수 있습니다. 또한 귀하의 쿼리를 좀 더 깨끗하게 만들 것입니다 ... 적어도 그것은 2 센트입니다.

DELIMITER $$

create function calcDistance(lat float, lng float, pnt_lat float, pnt_lng float)

Returns float
BEGIN

Declare dist float;
SET dist =
  3959 * acos (
  cos ( radians(pnt_lat) )
  * cos( radians( lat ) )
  * cos( radians( lng ) - radians(pnt_lng) )
  + sin ( radians(pnt_lat) )
  * sin( radians( lat ) )
);

RETURN dist;

END

코드 스타일을 수정하면 답변이 공개됩니다. 올바른 방법
Vasilii Suricov

0

여기 내 쿼리 변형이 약간 더 쉬워 보입니다 ( http://dexxtr.com/post/83498801191/how-to-determine-point-inside-circle-using-mysql )

SELECT 
    *
FROM 
    `locator`
WHERE
    SQRT(POW(X(`center`) - 49.843317 , 2) + POW(Y(`center`) - 24.026642, 2)) * 100 < `radius`

4
더 쉽지만 지구가 구부러져 있다는 사실은 무시합니다.
Tim Rijavec

정확한 수식이 필요합니다. 아마도 이것은 단거리에서만 좋을 것입니다 : D
Jethro

나중에 미사일을 발사 할까?
데니스 브라가

1
@DennisBraga-그렇다면 그렇다면이 질문은 주제에 맞지 않고 http://globalthermonuclearwar.stackexchange.com ...에 더 적합합니다 .
ashleedawg
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.