2013-12-13 2 views
0

MySQL 테이블에는 사용자와 점수라는 두 개의 열이 있습니다.각 사용자의 MySQL 두 번째 최대 값

각 사용자의 두 번째 최대 점수를 가진 표를 얻으려면 어떻게해야합니까? 그리고이 두 번째 최대 값의 최대 값은?

User | Score 
X | 12 
Y | 21 

그리고 두 번째 최대 값의 최대 또 하나 : 나는 두 번째 최대 값과 테이블을 얻고 싶은

User | Score 
X  50 
Y  74 
X  9 
X  12 
Y  21 

: 즉

,이 테이블을 가질 수있다 :

Score 
21 

참고 : 성능이 중요합니다. 나는 가장 빠른 해결책이라고 생각할 것입니다. 각 사용자 MAX없이

+0

'두 번째 최대 점수'를 더 잘 정의하십시오. – AmazingDreams

+1

LIMIT 1,1과 GROUP BY를 결합하려고했습니다. 그러나 그것은 작동하지 않습니다. –

+0

'OFFSET 1 LIMIT 1' 시도해 봤어? – AmazingDreams

답변

1
DROP TABLE IF EXISTS scores; 

CREATE TABLE scores(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,user CHAR(1) NOT NULL,score INT NOT NULL,INDEX(user,score)); 

INSERT INTO scores (user,score) 
VALUES 
('X',50), 
('Y',74), 
('X',9), 
('X',12), 
('Y',21); 

SELECT x.* 
    FROM scores x 
    JOIN scores y 
    ON y.user = x.user 
    AND y.score >= x.score 
GROUP 
    BY x.user 
    , x.score 
HAVING COUNT(*) = 2 
ORDER 
    BY score DESC 
LIMIT 1; 

+----+------+-------+ 
| id | user | score | 
+----+------+-------+ 
| 5 | Y | 21 | 
+----+------+-------+ 

같은 사용자가 당신은 어딘가에서 DISTINCT를 포함해야합니다, 두 번 같은 점수를 가질 수있는 기회가 있다면 -하지만 난 독자들에게 운동으로 떠날거야가.

성능이 문제가되면 다음과 유사한 솔루션이 훨씬 더 확장 가능합니다. 나는 여러 변수를 추적 할 때 뒤죽박죽이되는 습관을 가지고 있기 때문에 나는 ... '유사'라고 두 명의 사용자와 약의 색인 테이블에

SELECT id,user,score 
    FROM 
    (
    SELECT id 
    , user 
    , score 
    , @puser := @cuser 
    , @prev := @curr 
    , @cuser := user 
    , @curr := score 
    , @rank := IF(@puser = @cuser,IF(@prev = @curr, @rank, @rank+1),@rank:=1) rank 
    FROM scores 
    JOIN (SELECT @cuser :=null,@puser := null,@curr := null, @prev := null, @rank := 0) sel1 
ORDER 
    BY user, score DESC 
    ) x 
    WHERE rank = 2 
    ORDER BY score DESC LIMIT 1; 

+----+------+-------+ 
| id | user | score | 
+----+------+-------+ 
| 5 | Y | 21 | 
+----+------+-------+ 

빠른 테스트 10,000 행. 쿼리 1은 15 초 만에 완료되고 쿼리 2는 1/100 초 만에 완료됩니다!

+0

귀하의 질의를 정확히 이해하면 번호가 number_of_scores * number_of_scores 인 표가 사용됩니다. 그렇다면 대형 테이블을위한 좋은 솔루션이 아닙니다. –

+0

대용량이란 30 초 동안 계산 한 후 데이터베이스에서 쿼리를 중지했음을 의미합니다. –

+0

ID가 다른 열이 있습니다. –

0

모든 항목이 두 번째의 최대치

SELECT t1.user, t1.score FROM t t1, 
    (SELECT t2.user, t2.score FROM t t2 WHERE t2.score = 
     (SELECT MAX(t3.score) FROM t t3 WHERE t2.user = t3.user)) t4 
WHERE t1.user = t4.user AND t1.score <> t4.score 
GROUP BY t1.user DESC ORDER BY t1.user, t1.score; 

MAX :

SELECT t1.user, MAX(t1.score) FROM t t1, 
    (SELECT t2.user, t2.score FROM t t2 WHERE t2.score = 
     (SELECT MAX(t3.score) FROM t t3 WHERE t2.user = t3.user)) t4 
WHERE t1.user = t4.user AND t1.score <> t4.score; 

SQLFiddle :http://sqlfiddle.com/#!2/f2e717/29

SELECT DISTINCT `score` FROM `table_name` ORDER BY `score` DESC LIMIT 1,1 

참고 : 3,691,363,210

+0

각 사용자의 두 번째 최대 값을 원해. –

+0

그러나이 쿼리는 나에게 몇 가지 아이디어를 제공합니다. –

+0

표의 설명과 예제 데이터를 제공하면 도움이 될 수 있습니다. – Minoru

0

이 당신에게 두 번째로 높은 점수를 줄 것이다 당신은 당신의 테이블의 깨끗한 사진을 우리에게 매우 helpfull을 제공합니다.

관련 문제