2015-01-14 10 views
3

그룹 수가 4보다 큰 경우에만 내 DB에서지도 항목 목록을 반환하려고합니다. 그렇지 않으면 원하지 않습니다. 그룹화 할 항목.COUNT (*)> X 일 경우 그룹화, 그렇지 않으면 그룹화하지 않음

내 프로젝트는 설정된 영역 내의 모든 항목을 반환하도록 작성되었으며 그룹화를 사용하여 해당 영역을 그리드로 분할합니다. 그리드의 각 셀에 너무 많은 결과가있는 경우 단일 항목 표식 대신 그룹 수와 함께 그룹 표식을 표시합니다.

나의 현재 쿼리는 COUNT (*) 내가 뭘하고 싶은 것은 유일한 그룹이

SELECT *, COUNT(*) as groupCount, floor(longitude/0.0007) AS groupLong, floor(latitude/0.0007) AS groupLat 
FROM items 
WHERE longitude>=151.1 
    AND longitude<=151.2 
    AND latitude>=-33.9 
    AND latitude<=-33.8 
GROUP BY floor(longitude/0.0007), floor(latitude/0.0007) 

인에 의해 항목이 그룹화되어 있는지 확인하기 위해 노력하고있는 항목의 경우 그룹의 그룹 수> 4 항목 < = 4는 그룹화되지 않은 항목으로 반환됩니다.

나는 HAVING COUNT(*)>4을 사용하여 5 이상의 그룹 만 반환 할 수 있다는 것을 알고 있지만 4 세 이하의 그룹에 속한 그룹 해제되지 않은 항목을 반환하려면 어떻게해야합니까?

결과를 얻기 위해 두 가지 쿼리를 수행하게되어 기쁩니다. 그렇다면 그것을 수행하는 방법이 있다면 그것은 좋을 것입니다!

+0

데이터베이스 엔진을 전환 할 수있는 옵션이있는 경우이 기능은 창 기능에 유용합니다. MySQL은 그들을 지원하지 않지만 PostgreSQL은 지원합니다. –

답변

2

여기 내 솔루션에 대한 SQL 바이올린의 : http://sqlfiddle.com/#!8/e40ba/1

아이디어는 먼저 그룹이 하위 쿼리 grouping에서 수행되는이 될 것입니다 무엇인지 파악하는 것입니다. 그런 다음이 그룹을 원래 테이블에 조인하지만 그룹에없는 모든 값은 그룹화 열에 대해 null을 가질 수 있도록 왼쪽 외부 조인을 사용합니다. 마지막으로 AVG을 사용하여 그룹의 대표 좌표를 제안합니다. 그룹화되지 않은 값의 경우 이는 좌표 자체가됩니다.

필자는 실제로 테스트와 벤치마킹을 수행하지 않고 이것을 사용하지 말 것을 권장합니다. items이 큰 경우 그 참여는 아마도 끔찍할 것입니다. 난 정말이 쿼리를 단일 쿼리에서 수행하는 방법을 찾고 싶었습니다. 앞에서 언급 한 바와 같이,이 작업을 수행하는 올바른 방법은 윈도우 함수를 사용하는 것이지만 MySQL에는 그러한 함수가 없습니다.

SELECT AVG(longitude) AS longitude 
    , AVG(latitude) AS latitude 
    , COUNT(*) AS count 

FROM items 
    LEFT OUTER JOIN 
     (SELECT COUNT(*) AS group_count 
       , FLOOR(longitude/0.0007) AS group_longitude 
       , FLOOR(latitude/0.0007) AS group_latitude 
      FROM items 
      -- Repeat the filter to avoid computing unnecessary groups 
      WHERE longitude >= 151.1 
      AND longitude <= 151.2 
      AND latitude >= -33.9 
      AND latitude <= -33.8 
      GROUP BY group_longitude, group_latitude 
      HAVING group_count > 4 
     ) AS grouping 
    -- Match each row up with its group 
    ON FLOOR(longitude/0.0007) = group_longitude 
    AND FLOOR(latitude/0.0007) = group_latitude 

WHERE longitude >= 151.1 
    AND longitude <= 151.2 
    AND latitude >= -33.9 
    AND latitude <= -33.8 

GROUP BY COALESCE(group_longitude, id) 
     , COALESCE(group_latitude, id) 
+0

정말 대단한 생각입니다. 제 경우에는 수백만 행에서 조건없이 그룹화하는 것은 80ms이고 조건 (이 전략)은 약 160ms입니다. 그렇게 빠르지는 않아요. – atomkirk

1

이 문제를 해결하기 위해 두 하위 쿼리 결과를 조합으로 사용할 수 있다고 생각합니다. 아마도 두 부분을 나누어서 subselect를 사용할 수 있습니다. 첫 번째 부분은 COUNT (*)> 4 조건 결과를 얻었고 두 번째 항목은 다른 items.id를 가져 와서 다른 모든 항목을 검색했습니다.