2014-02-22 6 views
0

내가 위치를 사용하여 위치의 테이블을 조회하는이 SQL 쓴이 Google tutorial중복 레코드 크로스 가입하고 Hversine 공식

의 수정을 완료하기 위해 노력하고있어 "이름을."사용 위치의 이름이 주어지면 쿼리는 근접 지역의 피자 레스토랑을 반환합니다. 이것을 달성하기 위해 레스토랑 위치의 내 테이블에 십자가를 긋고, "마커"라는 제목을 붙이고 Haversine 공식을 사용하여 거리를 계산했습니다.

SELECT m.address, 
     m.name, 
     m.lat, 
     m.lng, 
     (3959 * ACOS(COS(RADIANS(poi.lat)) * 
     COS(RADIANS(m.lat)) * 
     COS(RADIANS(m.lng) - RADIANS(poi.lng)) + SIN(RADIANS(poi.lat))* 
     SIN(RADIANS(m.lat)))) AS distance 
    FROM markers poi 
     CROSS JOIN markers m 
    WHERE poi.address LIKE "%myrtle beach%" 
      AND poi.id <> m.id HAVING distance < 200 
    ORDER BY distance LIMIT 0,20 

쿼리는 예상 된 결과를 반환하지만 관심의 포인트는이 경우에, 지정된 영역 밖에있는 경우 "머틀 비치,"나는 경기 당 중복 레코드를 얻을. CROSS JOIN이 DISTINCT select로 쉽게 수정 될 수 있기 때문입니다. 그러나 "lng"및 "lat"필드는 FLOAT 유형이므로 중복 된 레코드의 경우에도 거리 계산이 동일하지 않습니다. |

3901 북한 킹스 하이웨이 스위트 룸 1, 머틀 비치, 사우스 캐롤라이나 : 여기

은 수익의 일부입니다 시카고의 동쪽 피자 회사 | 33.716099 -78.855583 | 4.0285562196955125

1706 S 킹스 하이웨이 # A, 머틀 비치, 사우스 캐롤라이나 | 도미노 피자 : 머틀 비치 | 33.674881 | -78.905144 | 4.0285562196955125

82 Wentworth St, Charleston, SC | Andolinis 피자 | 2.782330 | -79.934235 | 85.68177495224947

82 Wentworth St, Charleston, SC | Andolinis 피자 | 32.782330 | -79.934235 | 89.71000040441085

114 Jungle Rd, Edisto Island, SC | Edisto Beach Inc의 벅스 피자 | 32.503971 -80.297951 | 114.22243529200529

114 Jungle Rd, Edisto Island, SC | Edisto Beach Inc의 벅스 피자 | 32.503971 -80.297951 | 118.2509427998286 "여기에서 이동하는 위치에

어떤 제안

+0

dups를 보여주는 샘플 입력 및 출력을 게시 할 수 있습니까? 그리고 가독성을 위해 [Haversine 함수의 존재]를 가정하는 편집을 제안합니다 (http://stackoverflow.com/questions/6385452/a-custom-mysql-function-to-calculate-the- haversine-distance). – bishop

+0

@Brandon Buster 데이터 샘플을 제공 할 수 있습니까? 또한 관심 장소에 따라 무엇을 의미합니까? 내가보기에는 수동으로 입력 한 데이터는 % myrtle beach %입니다. 너 무슨 짓을하려는거야? 이 질문은 이해하기가 약간 어렵고 설명과 세부 사항이 더 필요합니다. –

+0

죄송합니다. 서로 다른 상황에서 "관심 지점"이라는 용어를 사용했습니다. 이 예제에서 중요한 점은 Myrtle Beach뿐입니다. 내가 원하는 데이터는 200 마일 반경 안에있는 피자 레스토랑입니다. 몇 가지 샘플 데이터와 추가 정보로 게시물을 편집하겠습니다. –

답변

1

시도 : 두 지점 모두 일치하기 때문에 중복 결과를 얻고있다

select distinct x.address, x.name, y.lat, y.lng, x.distance 
    from (SELECT m.address, 
       m.name, 
       m.lat, 
       m.lng, 
       (3959 * 
       ACOS(COS(RADIANS(poi.lat)) * COS(RADIANS(m.lat)) * 
        COS(RADIANS(m.lng) - RADIANS(poi.lng)) + 
        SIN(RADIANS(poi.lat)) * SIN(RADIANS(m.lat)))) AS distance 
      FROM markers poi 
     cross JOIN markers m 
     WHERE poi.address LIKE "%myrtle beach%" 
      and poi.id <> m.id HAVING distance < 200) x 
    join markers y 
    on x.address = y.address 
    and x.name = y.name 
    and x.lat = y.lat 
    and x.lng = y.lng 
order by x.distance limit 0, 20 
+0

감사합니다. 무엇이 효과적인 해결책이 될지를 지적하십시오. 세 번째 테이블 조인을 수행하지 않는 것이 좋습니다. 이것이 유일한 대답으로 밝혀지면 (아마도 그렇다) 나는 이것을 답으로 표시 할 것이다. –

1

". 머틀 비치 "를 poi.id < m.id 같은 조건을 사용하여 당신은 단지 하나의 일치를 얻을 수 있도록

예 :.

poi id m id distance 
1   2  100 
2   1  100 
을 17,451,515,

검색어 : 당신이 진정으로 관심의 포인트로 마커의 단일 행이있는 경우

SELECT 
    m.address, 
    m.name, 
    m.lat, 
    m.lng, 
    (3959 * ACOS(COS(RADIANS(poi.lat)) * 
    COS(RADIANS(m.lat)) * 
    COS(RADIANS(m.lng) - RADIANS(poi.lng)) + SIN(RADIANS(poi.lat))* 
    SIN(RADIANS(m.lat)))) AS distance 
FROM markers poi 
CROSS JOIN markers m 
WHERE 
    (poi.address LIKE "%myrtle beach%" OR m.address LIKE "%myrtle beach%") 
    AND poi.id < m.id 
HAVING distance < 200 
ORDER BY distance LIMIT 0,20 

또는 대신 주소에있는 모든 경기의를 지정합니다. 그런 다음 poi.id <> m.id의 상태는 중복이 없음을 보장합니다.

SELECT 
    m.address, 
    m.name, 
    m.lat, 
    m.lng, 
    (3959 * ACOS(COS(RADIANS(poi.lat)) * 
    COS(RADIANS(m.lat)) * 
    COS(RADIANS(m.lng) - RADIANS(poi.lng)) + SIN(RADIANS(poi.lat))* 
    SIN(RADIANS(m.lat)))) AS distance 
FROM markers poi 
CROSS JOIN markers m 
WHERE 
    poi.id = (SELECT TOP(1) id FROM markers WHERE address LIKE "%myrtle beach%") 
    AND poi.id <> m.id 
HAVING distance < 200 
ORDER BY distance LIMIT 0,20 
+0

답장을 보내 주셔서 감사합니다. 중복을 제거하지만, 일치하는 모든 레코드가 내 대상 영역에서 발견 된 레코드보다 높은 ID를 가짐을 전제로합니다. 항상 그렇지는 않습니다. 그것은 내가 SQL을 작성하는 방법에 대해 다른 관점을 제공하고있다. –

+0

@BrandonBuster, 첫 번째 쿼리에서 더 높은 번호의 행이나 낮은 번호의 행 중 하나가 일치 할 수 있으므로이를 가정하지 않습니다. 두 번째 쿼리에서는'> '비교를 사용하지 않습니다. – Mitch

0

모든 사람의 응답을 검토하면 나에게 맞는 생각이 들게됩니다. 왜 내가 중복 된 결과를 얻었는지 묻는 대신 두 개의 Myrtle Beach 위치 중 어느 것이 거리를 계산하는 쿼리인지 궁금해하기 시작했습니다. 대답은 둘 다였습니다. 그리고 이것이 내가 왜 매치마다 두 기록을 얻었는지 설명합니다.이 임의로이 진원지로 찾은 첫 번째 레스토랑을 사용하기 때문에

SELECT m.address, m.name, m.lat, m.lng, (3959 
    * ACOS(COS(RADIANS(poi.lat)) * COS(RADIANS(m.lat)) 
    * COS(RADIANS(m.lng) - RADIANS(poi.lng)) + SIN(RADIANS(poi.lat)) 
    * SIN(RADIANS(m.lat))))  AS distance 
FROM markers m 
cross JOIN (
    select name, lat, lng from markers 
    where address like '%myrtle beach %' 
    limit 1 
) poi 
HAVING distance < 200 
ORDER BY name 
LIMIT 0, 20 

이것은 나에게 가장 정확한 거리 계산을주지 않습니다

여기 내 솔루션입니다. 하지만 당장의 목적으로는 충분합니다. 이 앱이 프로덕션 준비가되었다고 생각합니다. 도심 좌표를 포함 할 도시의 두 번째 테이블이 필요합니다.