2012-04-01 2 views
4

MySQL 테이블에서 여러 "상위 X"결과를 얻는 더 좋은 방법이 있습니까? 다른 foo는의 수가 적을 때 나는 노조 쉽게이를 수 있어요 : 나는 분명히 foo는의 각 값에 대해 노동 조합을 계속 추가 할 수MySQL 테이블에서 각 개인의 최상위 X 레코드 선택

(SELECT foo,score FROM tablebar WHERE (foo = 'abc') ORDER BY score DESC LIMIT 10) 
UNION 
(SELECT foo,score FROM tablebar WHERE (foo = 'def') ORDER BY score DESC LIMIT 10) 

. 그러나 이것은 foo에 대해 500 가지 이상의 다른 값이있을 때 실용적이지 않으며 각각의 최상위 X가 필요합니다.

+0

대담하게도 현재 성능에 근접한 해결책이 있습니다. – zerkms

답변

9

이러한 종류의 쿼리는 "그룹당 최대"점수가 'foo'값인 상위 "그룹당"의 의미로 해석 될 수 있습니다.

이 질문에 기쁨을내어 this link을 살펴 보시고, 쿼리를 수행하고 점진적으로 최적화하는 방법으로 시작하는 것이 좋습니다.

set @num := 0, @foo := ''; 
select foo, score 
from (
    select foo, score, 
     @num := if(@foo = foo, @num + 1, 1) as row_number, 
     @foo := foo as dummy 
    from tablebar 
    where foo IN ('abc','def') 
    order by foo, score DESC  
) as x where x.row_number <= 10; 

당신이 foo모든 수준에 걸쳐이 작업을 수행하고자한다면

(즉,이 GROUP BY foo을하고 상상), 당신은 where foo in ... 라인을 생략 할 수 있습니다.

는 기본적으로 내부 쿼리 (SELECT foo, score FROM tablebar WHERE foo IN ('abc','def') ORDER BY foo, score DESC)는 내림차순 점수를 다음 foo에 의해 처음으로 주문하고, 테이블에서 fooscore을 잡고.

@num := ...은 모든 행의 값이 증가하며, 각각의 새로운 값인 foo마다 1로 재설정됩니다. 즉, @num은 행 번호/순위 일뿐입니다 (의미를 보려면 자체 쿼리를 실행 해보십시오).

외부 쿼리는 그 다음 순위/로우 수가 10 이하인 행을 선택

참고

UNION와 원래 검색어가 중복 제거 그렇다면 foo='abc' 대한 상위 10 득점 가 모두 100이면 (foo,score) 쌍이 10 번 복제되므로 하나의 행만 반환됩니다. 이것은 중복을 반환합니다.

+0

대단히 감사합니다. 실제로 검색 한 페이지에 비틀 거 렸지만, 빠른 검색을 통해 단 하나의 최상의 정보 만 표시한다고 잘못 생각했습니다. 각 그룹의 행. 내가 더 자세히 살펴 봐야 할 것 같아. – Exupery

관련 문제