2015-11-25 2 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

Но то, что я попытка сделать это только приращение переменной, если значение уровня изменяется. Итак, если две строки, имеющие одинаковый уровень, имеют одинаковый ранг 8.

Любые идеи? Благодарю.

+0

Второй ответ на вопрос, который я помечена как дубликат держит ответ. Это в основном MySQL-версия функции windowed rank(). – jpw

+0

Я не уверен, что это будет считаться дубликатом - мы видели гораздо худшие вопросы с похожими ответами на SO. Это должно помочь: 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; 
Смежные вопросы