2010-04-03 4 views
0

PostgreSQL 데이터베이스에 POI (Point Of Interest)를 저장하고 PHP 스크립트를 통해 Android 응용 프로그램으로 가져옵니다. 인터넷 사용을 줄이기 위해 현재 표시된 지역 근처에 포인트가 있는지 모바일 앱에 알리고 싶습니다. 가장 가까운 지점 등 이미 검색 한 가장 북쪽의 왼쪽 이미 검색 가장 서쪽의 (웨스트), 북미 (위의 가장 가까운 지점)에 :상자에 포함 된 왼쪽 상단 오른쪽 상단 위치 |

내 생각은 즉 이미 검색된 모든 점을 포함하는 사각형의 경계를 (저장하는 것입니다) 화면의 가장자리가이 범위를 벗어날 때 다음 질의를 할 것입니다.

현재 내가 "하나의 화면"에 포인트를 검색 할 수 있습니다 사용 (현재 표시된지도에 의해 커버되는 영역에서) :

SELECT * FROM ch WHERE loc <@ (box '((".-$latSpan.", ".$lonSpan."),(".$latSpan.", ".-$lonSpan."))' + point '".$loc."') 

지금 내가보다, 각각의 방향으로 4 개의 가장 먼 점을 알 필요가 다음 4 개의 "원격"지점을 검색 할 수 있습니다.

PostgreSQL에서 해당 점 (또는 상자)을 직접 가져올 수 있습니까 (일부 "집계 지점"기능 사용) 할 수 있습니까?

+0

상자에있는 값의 순서는 확실합니까? Y (수직)의 X (가로) 좌표와 경도에 위도 극단 (N/S)을 저장하는 것 같습니다. 상자가'box ((-longSpan, latSpan), (longSpan, -latSpan))'이 될 것으로 기대합니다. – outis

답변

0

당신은 따라서 일부 minimal quantity와 행에 대해 다른 열을 찾는 문제를 줄이고, 가장 가까운 거리를 찾기 위해 MIN 집계 함수와 결합 연산자 (<->) 거리 - 더 사용할 수 있습니다./right/above/below 연산자 (<<, >>, |>>, <<|)의 왼쪽은 상자의 한쪽으로 포인트를 제한하는 데 사용할 수 있습니다. 두 개의 서로 다른 점이 같은 거리를 가질 수 있으므로 limit 결과가 1 행이됩니다. 좌표가 아래로 증가 (북쪽과 동쪽을 증가하지 않고지도 방향보다) 오른쪽으로 화면 방향을 가정 할 때, 우리가 얻을 :

-- Above, or North 
SELECT * FROM ch WHERE loc <<| screen AND (loc <-> screen) = (
    SELECT MIN(loc <-> screen) AS mindist FROM ch 
    WHERE loc <<| screen 
) LIMIT 1 

-- Right, or East 
SELECT * FROM ch WHERE loc >> screen AND (loc <-> screen) = (
    SELECT MIN(loc <-> screen) AS mindist FROM ch 
    WHERE loc >> screen 
) LIMIT 1 

-- Below, or South 
SELECT * FROM ch WHERE loc |>> screen AND (loc <-> screen) = (
    SELECT MIN(loc <-> screen) AS mindist FROM ch 
    WHERE loc |>> screen 
) LIMIT 1 

-- Left, or West 
SELECT * FROM ch WHERE loc << screen AND (loc <-> screen) = (
    SELECT MIN(loc <-> screen) AS mindist FROM ch 
    WHERE loc << screen 
) LIMIT 1 

참고 수평 방향으로 가장 가까운 지점도 가장 가까운 포인트가 될 수 있음 수직 방향으로; 즉, 위의 네 문장의 결합은 네 줄보다 작을 수 있습니다.

우리가 할 수와 가장 가까운 4 포인트를 얻을 :

SELECT *, (loc <-> screen) AS distance FROM ch 
    WHERE NOT loc <@ screen 
    ORDER BY distance 
    LIMIT 4 

그러나, 가장 가까운 지점의 일부가 서로 같은 방향에있을 수 있습니다. DBMS를 사용할 수 있기 때문에

우리는

SELECT *, (loc <-> screen) AS distance FROM ch 
    WHERE distance = (
     SELECT MIN(loc <-> screen) AS mindist FROM ch 
) 
    LIMIT 1 

또는

SELECT *, (loc <-> screen) AS distance FROM ch 
    WHERE NOT loc <@ screen 
    ORDER BY distance 
    LIMIT 1 

열의 최소 (또는 최대)을 계산

는, 첫 번째 바람직 할 것으로 전반적인 가장 가까운 지점을 얻을 수 있습니다 열 (있는 경우)에 대한 색인이며 테이블을 스캔 할 필요가 없습니다. 거리는 계산 된 값이기 때문에 항상 테이블 스캔이 필요하며 쿼리의 성능은 비슷합니다. query analysis은 진술을 선호하는 다른 이유를 나타낼 수 있으므로 접근 방법을 선택하기 전에 수행해야합니다.

+0

답변을 "컴파일"할 시간이 필요합니다 ... 하지만, 'SELECT * FROM ch WHERE loc << | 화면 AND (loc <-> 화면) = (SELECT MIN (loc <-> 화면) 마음에서 ch where where | << 화면) LIMIT 1' 이상'SELECT * FROM ch WHERE loc << | 화면 및 주문 (위치 <-> 화면) ASC LIMIT 1'? – skyman

+0

@skyman : 마지막 코멘트를 읽으십시오. 나는 당신이 언급 한 두 가지의 후자가 더 잘 수행 될 것이라고 의심하지만 확실한 질의 분석을 실행합니다. – outis

관련 문제