2014-06-09 91 views
5

我是新來的sql,我從來沒有在mysql中使用變量或條件,但知道來自其他編程語言。由於幾天我試圖找到排名用戶評分的方法。我閱讀了大量的文章,以及在stackoverflow上提出的問題,最後我找到了一個幾乎像我想要的那樣的解決方案。MySQL排名關係

SELECT 
    score_users.uid, 
    score_users.score, 
    @prev := @curr, 
    @curr := score, 
    @rank := IF(@prev = @curr, @rank, @rank +1) AS rank 
FROM 
    score_users, 
    (SELECT @curr := null, @prev := null, @rank := 0) tmp_tbl 
WHERE 
    score_users.matchday = 1 
ORDER BY 
    score_users.score DESC 

但我的問題是領帶分數。我不希望得到連續的行列,像這樣:

+------------+------+--------+ 
| uid | name | rank | score | 
+------------+------+--------+ 
| 4 | Jon | 1 | 20 | 
| 1 | Jane | 2 | 19 | 
| 2 | Fred | 2 | 19 | 
| 9 | July | 3 | 18 | 
| 7 | Mary | 4 | 17 | 
| 3 | Toni | 5 | 12 | 
| 5 | Steve | 5 | 12 | 
| 6 | Peter | 6 | 11 | 
| 8 | Nina | 7 | 10 | 
+------------+------+--------+ 

我想獲得這樣的結果:

+------------+------+--------+ 
| uid | name | rank | score | 
+------------+------+--------+ 
| 4 | Jon | 1 | 20 | 
| 1 | Jane | 2 | 19 | 
| 2 | Fred | 2 | 19 | 
| 9 | July | 4 | 18 | 
| 7 | Mary | 5 | 17 | 
| 3 | Toni | 6 | 12 | 
| 5 | Steve | 6 | 12 | 
| 6 | Peter | 8 | 11 | 
| 8 | Nina | 9 | 10 | 
+------------+------+--------+ 

我想我必須創建一個新的臨時表,還有一些如果條件,但我找不到解決辦法,變得絕望! 另外,我必須密切注意表現,也許有更好的方法來獲得排名,因爲我做到了?我會非常感謝提示或一些代碼片段。

+0

我生成SQL之外的排名,因爲它更容易與你使用任何程序(按分數排名是足夠了)做的。做你正在做的事情在MySQL中很複雜! – serakfalcon

回答

3

您可以使用另一個變量來計算同一行列所以不是由1遞增@rank的,您可以通過計數器值遞增@rank,像這樣:

SELECT 
    score_users.uid, 
    score_users.score, 
    @prev := @curr, 
    @curr := score, 
    @rank := IF(@prev = @curr, @rank, @rank + @i) AS rank, 
    IF(@prev <> score, @i:=1, @i:[email protected]+1) AS counter 
FROM 
    score_users, 
    (SELECT @curr := null, @prev := null, @rank := 0, @i := 0) tmp_tbl 
WHERE 
    score_users.matchday = 1 
ORDER BY 
    score_users.score DESC 
+1

謝謝阿齊茲,這個作品非常好。我只是在子選擇中將@rank設置爲1,否則排名從0開始!乾杯 – FredFus

0

添加另一個級別的字段,它總是遞增。如果該值匹配你使用你現有的等級(不增加),如果不是,你使用你總是增加的等級。

SELECT 
    score_users.uid, 
    score_users.score, 
    @prev := @curr, 
    @curr := score, 
    @rank1 := @rank1 + 1, 
    @rank := IF(@prev = @curr, @rank, @rank1) AS rank 
FROM 
    score_users, 
    (SELECT @curr := null, @prev := null, @rank := 0, @rank1 := 0) tmp_tbl 
WHERE 
    score_users.matchday = 1 
ORDER BY 
    score_users.score DESC 
0

在關係上,您可能想要跳過並將當前行數用作下一個排名的下一個不匹配的分數值行。 以下應該可以幫助您

SELECT 
    score_users.uid 
    , @curr_score := score_users.score as score, 
    , case when @prev_score = @curr_score then @rank := @rank 
     else @rank := (@curr_row + 1) -- <- this is what you require 
    end as rank 
    , @curr_row := (@curr_row + 1) as curr_row 
    , @prev_score := @curr_score 
FROM 
    score_users, 
    (SELECT @curr_score := 0, @prev_score := 0 
     , @curr_row := 0, @rank := 0) initializer 
WHERE 
    score_users.matchday = 1 
ORDER BY 
    score_users.score DESC