2011-11-10 2 views
-1

처음 게시 할 때 모범 사례를 따르려고합니다.MySQL 컬럼 데이터 그룹화

사용자 위치를 측정하는 MySQL 쿼리를 작성하려고합니다 (위도와 경도는 각각 $Lat$Lng). 쿼리는 사용자에게 가장 가까운 50 개의 스테이션을 반환해야합니다.

문제는 내 테이블의 데이터에 각 스테이션의 위치가 포함되어 있으며 입구 당 입구에만 스테이션 당 가장 가까운 스테이션 입구가 필요합니다!

  1. 는 ID, 위도, LNG, 역의 운행 데이터와 경로
  2. 를 선택 :

    SELECT id, lat, lng, station_name, routes, 
        (3959 * acos(cos(radians($Lat)) 
        * cos(radians(lat)) * cos(radians(lng) - 
        radians($Lng)) + sin(radians($Lat)) * sin(radians(lat)))) AS distance 
    FROM subway_stations ORDER BY distance LIMIT 0 , 50; 
    

    위 MySQL의 쿼리는 다음과 수행 :

    내 쿼리입니다 각 스테이션의 lat 및 lng를 사용자의 Lat 및 lng로 측정 - 해당 데이터를 '거리'로 저장
  3. 반환 50 개 가까운 결과
  4. 나는 이러한 결과 함께 역 당 하나의 레코드가 반환되도록 그룹에 필요

, 사용자에게 가장 가까운 역 입구 거리 열에서 가장 낮은 값을 가진 하나 .

나는 GROUP BY을 사용해 보았지만 반환 된 결과가 원하는 것이 아니기 때문에 잘못 구현 한 것 같습니다.

답변

0

은 샘플 데이터베이스를 설정하지 않고 알고 어렵다,하지만 난 당신이 다음과 같이 변경 만들고 싶어 의심 :

  1. 이 쿼리의 끝에

  2. 모든 selectgroup by station_name, id, lat, lng 추가하기 group by 절의 일부가 아닌 필드에는 집계 함수가 필요합니다. 대부분 분명, distance는해야 min(...)

  3. 내가 orderlimit 절을 사용할 수 있는지 확실하지 않습니다 필요합니다. 문제가있는 경우 일시적으로 꺼내어이 작업을 많이하십시오. 편의상이 쿼리를 Q1이라고 부릅니다.

  4. limit 절을 사용할 수 없으면 (실험 및 참조) 중첩 된 쿼리가 필요합니다. 그러면 select * from (...Q1...) t1 ORDER BY distance LIMIT 0,50처럼 보일 것입니다. t1에는 내부 선택에 임시 이름이 할당되었지만이 쿼리에는 실제로 사용되지 않았지만 구문에 필요했습니다.

  5. 최적화로 Q1 쿼리에 having 절을 추가 할 수 있습니다. 즉, 경계 거리를 알고있는 경우 HAVING distance<XXXXX을 추가하십시오. 3 단계

주 - (5)가 필요하지 않을 수있다, 나는 3 단계

+0

'station_name, id, lat, lng의 그룹'을 쿼리에 추가하면 기본적으로 그룹화하지 않는 것과 동일합니다. –

+0

나는'station_name'이 유일하게'id','lat','lng'을'id'를 가능한 기본 키로 정의했다고 가정했습니다. 그러나 '이드'와 같은 원래 질문을 다시 읽는 것은 아마도 개인의 입장을 나타낼 것입니다. 그래서 네 말이 맞을거야. 나는 다시 생각하고있어. – Pursuit

+0

@Sam 귀하의 답변이 정확합니다. 원래의 질문에 답하기 위해'order by'와'limit' 절을 추가하기 만하면됩니다. (내 평판이 아직 충분하지 않아서 당신의 질문에 대해이 의견을 기재 할 수 없습니다). – Pursuit

0

당신이 각 스테이션에 대해 하나 개의 작은 기록을해야하는 경우이 가장 작은 거리 역 당 하나의 레코드 만 반환됩니다 그냥

$result = mysql_query("SELECT id, lat, lng, station_name, routes, MIN(
    (3959 * acos(cos(radians($Lat)) * cos(radians(lat)) * 
    cos(radians(lng) - radians($Lng)) + sin(radians($Lat)) * 
    sin(radians(lat)))) AS distance) 
FROM subway_stations 
GROUP BY station_name; 

을 ... LIMIT 필요하지 않습니다.

+0

이것은 작동하지 않습니다. GROUP BY 절에 지정되지 않은 필드를 선택하면 결과가 정의되지 않습니다. 임의의 행에서 결과를 얻습니다. –

0

당신은 쉽게 시간 PHP와 역마다 가장 가까운 입구를 받고있을 수 있습니다 확실하지 않다.

이것은 실제로 자주 발생하는 문제로 해결하기 위해 하위 쿼리를 사용해야합니다. id은 단지 행 ID이며 각 스테이션마다 고유하지 않다고 가정합니다.

SELECT subway_stations.* FROM (
    SELECT station_name, MIN(
     (3959 * acos(cos(radians($Lat)) * cos(radians(lat)) * 
     cos(radians(lng) - radians($Lng)) + sin(radians($Lat)) * 
     sin(radians(lat)))) 
    ) AS distance 
    FROM subway_stations 
    GROUP BY station_name 
) AS min_distances 
JOIN subway_stations ON (
    min_distances.station_name = subway_stations.station_name 
    AND (3959 * acos(cos(radians($Lat)) * cos(radians(lat)) * 
     cos(radians(lng) - radians($Lng)) + sin(radians($Lat)) * 
     sin(radians(lat))) 
    ) = min_distances.distance 
) 

이 문제는 일반적인 '순수한 mysql'솔루션입니다. 그러나 거리를 계산하는 정도에 따라 다음과 같이 계산할 수 있습니다. - 초기 쿼리를 사용하고 PHP를 사용하여 각 스테이션의 최단 거리를 얻거나 OR - 위의 내부 쿼리를 실행하고 그 결과를 삽입하십시오. 그런 다음 임시 테이블에서 계산 된 거리로 대체 된 계산 된 거리를 제외하고는 위 쿼리와 동일한 작업을 수행합니다.