Leetcode: Rank Scores

Write a SQL query to rank scores. If there is a tie between two scores, both should have the same ranking. Note that after a tie, the next ranking number should be the next consecutive integer value. In other words, there should be no “holes” between ranks.

+—-+——-+
| Id | Score |
+—-+——-+
| 1 | 3.50 |
| 2 | 3.65 |
| 3 | 4.00 |
| 4 | 3.85 |
| 5 | 4.00 |
| 6 | 3.65 |
+—-+——-+
For example, given the above Scores table, your query should generate the following report (order by highest score):

+——-+——+
| Score | Rank |
+——-+——+
| 4.00 | 1 |
| 4.00 | 1 |
| 3.85 | 2 |
| 3.65 | 3 |
| 3.65 | 3 |
| 3.50 | 4 |
+——-+——+

Answer:

Get one Score from a, and Get the Rank from b.

The rank is the count of distinct value that larger then a.Score.

select a.Score, count(distinct(b.Score))
from Scores as a, Scores as b
where b.Score >= a.Score
group by b.Id
order by a.Score desc;

It is a correlated sub-query. Time Complexity is O(N^2). This method runs out of time.

Build a subTable and Put “distinct” in it.

SELECT Scores.Score, COUNT(Ranking.Score) AS RANK
  FROM Scores
     , (
       SELECT DISTINCT Score
         FROM Scores
       ) Ranking
 WHERE Scores.Score <= Ranking.Score
 GROUP BY Scores.Id
 ORDER BY Scores.Score DESC;

User-Defined Variables. So cool!

Initiate one variable in a select statement.
Then update the variable in another select statement.
Then build the format that required.

SELECT Score, Rank 
FROM
(
  SELECT    Score,
            @curRank := @curRank + IF(@prevScore = Score, 0, 1) AS Rank,
            @prevScore := Score
  FROM      Scores s, (SELECT @curRank := 0) c, (SELECT @prevScore := NULL) p
  ORDER BY  Score DESC
) t;

Refer to:
http://dev.mysql.com/doc/refman/5.0/en/user-variables.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章