2015-11-25 64 views
2

我有過每個結果循環和更新一列的查詢:更新是根據其在結果中的位置列

SET @counter = 0; 
UPDATE users SET rank_level = @counter := @counter + 1 ORDER BY level DESC; 
SELECT rank_level, level FROM users ORDER BY rank_level ASC; 

,輸出:

enter image description here

但我是什麼試圖做的只是在水平值變化時增加變量。所以在同一級別的兩行中,它們的排名也是相同的。

任何想法?謝謝。

+0

第二個答案給我打上了一個問題,重複持有回答。它基本上是窗口化的rank()函數的MySQL版本。 – jpw

+0

我不積極,這將被視爲重複 - 看到很多更糟糕的問題與類似的答案。這應該有所幫助:http://sqlfiddle.com/#!9/3e981/1 – sgeddes

+0

@sgeddes如果你真的相信這個問題不一樣,並且我指出的答案不適用,你確實有權力重新打開這個問題。我相信我的評估是正確的。 – jpw

回答

0

所以最後我用這個去:

SET @prev_value = NULL; 
SET @rank_count = 0; 

UPDATE users SET rank_level = CASE 
    WHEN @prev_value = level THEN @rank_count 
    WHEN @prev_value := level THEN @rank_count := @rank_count + 1 
END 
ORDER BY level DESC; 

基於這樣的回答:Rank function in MySQL

0

rank()在MySQL中有點棘手。一種方法是用一個相關子查詢:

select u.*, 
     (select count(*) + 1 
     from users u2 
     where u2.level < u.level 
     ) as rank 
from users u; 

這是棘手放入update。假設你有一個userId列,您可以使用join

update users u join 
     (select u.*, 
       (select count(*) + 1 
       from users u2 
       where u2.level < u.level 
       ) as rank 
     from users u 
     ) ur 
     on u.userId = ur.userId 
    set rank_level = rank; 

做與變量等級是相當棘手(row_number()dense_rank()更容易),因爲它需要三個變量。這裏是select版本:

select u.*, 
     (@r := if(@l = level, 
       if(@rn := @rn + 1, @r, @r) 
       if(@l := level, 
        @rn := @rn + 1, @rn := @rn + 1 
        ) 
       ) 
     ) as ranking 
from users u cross join 
    (select @l := -1, @rn : = 0, @r := 0) params 
order by level;