{{notification.text}}

MirGames

03.12.10 18:54
0
Короче, делаю рейтинг игрока. В базе есть поле rating - куда записывается текущий суммарный рейтинг игрока. Выбрать топ 100 понятно как:

select id,name from users order by rating desc limit 100


Еще я хочу показать игроку таблицу где он находится - скажем он на 1000м месте - надо показать от 950 до 1049 позиции.

Вопрос - как подсчитать позицию игрока и остальных?
Я сделал такое поле, как ratposition и такую процедурку

Код

DELIMITER $$

CREATE  PROCEDURE `UpdateRatpositions`()
BEGIN
DECLARE uid BIGINT;
DECLARE done
INT DEFAULT 0;
DECLARE cnt
BIGINT DEFAULT 1;        
DECLARE UUP_CUR  CURSOR FOR select id from users order by rating desc,level desc,raz desc;      
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;

open  UUP_CUR;    
REPEAT FETCH UUP_CUR INTO uid;
     if done=0 then
       update users set ratposition=cnt where id=uid;
       set cnt=cnt+1;
      end if;
    UNTIL done
END REPEAT;
close UUP_CUR;     END$$

DELIMITER;


Она вызывается раз в 15 минут.

Но на 150 тысячах зарегеных это очень медленно! Буквально 5-6 минут она работает (индексы верные). Может кто подскажет, есть ли способ быстрее однозначно определить позицию игрока в рейтинге?
#1
Хранитель Флейма
03.12.10 21:12
0
Woolf
Две стратегии:

1) Пересчет позиции раз в день, скажем в 00 по серверному времени.
2) Второй вариант завести два поля - одно - позиция в рейтинге (условно RatioPosition - RP), второе - внутренний порядок для сортировки (O). И два правила при обновлении рейтинга игрока:
а) Взяли текущий RP, и обновили все O с таким же R, уменьшив значения на 1.
б) Вычислили новый RP (например, SELECT COUNT(*) + 1 FROM <scheme>.RATIO WHERE Ratio < @NewRatio, где Ratio количественное измерение - кол-во опыта, например), обновили RP, а O выставили 1. Для всех таких же RP прибавили O + 1.

Тогда позиция в рейтинге вычисляется как RP + O.
#2
Хранитель Флейма
03.12.10 21:21
0
Точнее я тебя маленько обманул, когда RP обновляешь надо O выставлять 0, а не 1.
#3
Хранитель Флейма
03.12.10 21:31
0
Woolf
Куда убежал? :) А как же потрындеть?
#4
Хранитель Флейма
03.12.10 21:50
0
А выбор записей для отображения, стало быть делаешь так, хотя все зависит от твоих предпочтений:

Имеем @UserRatio игрока для которого отображаем рейтинг.

Код

SELECT <ПОЛЯ>
FROM <схема>.RATIOS AS RT
WHERE
  RT.Position + RT.Offset BETWEEN @UserRatio / 50 * 50 AND @UserRatio / 50 * 50 + 50
ORDER BY
  RT.Position + RT.Offset


Таким образом отобразим всех игроков по 50 на страницу. Наш игрок при этом будет где-то в промежутке ^_^
Отредактировано: 03.12.10 21:51
#5
magician
04.12.10 00:01
0
Код

SET @p := 0, @found := 0;

SELECT
  id, name, rating
  IF( @found := @found OR id = <id игрока>, 0, @p := @p + 1 )
FROM
  <таблица>
WHERE
  1
ORDER BY rating ASC/DESC;

SELECT @p AS position;


так должны узнать позицию нужного игрока
Отредактировано: 04.12.10 00:05
#6
Хранитель Флейма
04.12.10 02:22
0
magician
Игрок 100505-й в рейтинге. Выведи мне 100 записей с игроками на местах с 100450 по 100550.
#7
06.12.10 04:25
0
Said
Спасибо большое ) Пытаюсь уже реализовать.
#{{post.Index}}
{{post.Author.Login}}
{{post.CreatedDate | date:'dd.MM.yy HH:mm'}}
{{post.VotesRating}}
Отредактировано: {{post.UpdatedDate | date:'dd.MM.yy HH:mm'}}