2015-03-09 8 views
0

Мне нужно создать систему точек в MySQL, точки добавляются в зависимости от позиции определенного столбца. Пример: есть 5 игроков, игрок с самым высоким счетом в строке «Завоеватель» получает 5 очков, 2-й игрок получает 4 балла, 3-й игрок 3 балла и т. Д. Это хранимая процедура, которую я бы назвал при расчете очки:Обновление на основе численного значения строки

BEGIN 
select Player_name into @a from Player where Conqueror = (select max(Conqueror) from Player); 
select Player_name into @b from Player where Conqueror = (select max(Conqueror) from Player where Player_name != @a); 
select Player_name into @c from Player where Conqueror = (select max(Conqueror) from Player where Player_name != @a and Player_name != @b); 
select Player_name into @d from Player where Conqueror = (select max(Conqueror) from Player where Player_name != @a and Player_name [email protected] and Player_name [email protected]); 
select Player_name into @e from Player where Conqueror = (select max(Conqueror) from Player where Player_name != @a and Player_name [email protected] and Player_name [email protected] and Player_name [email protected]); 
select count(Conqueror) into @playernum from Player; 
update Player set Points = Points + @playernum where Player_name = @a; 
update Player set Points = Points + @playernum-1 where Player_name = @b; 
update Player set Points = Points + @playernum-2 where Player_name = @c; 
update Player set Points = Points + @playernum-3 where Player_name = @d; 
update Player set Points = Points + @playernum-4 where Player_name = @e; 
END 

Этот код выглядит ужасно, но он отлично работает, за исключением случаев, когда есть игроки с одинаковым счетом. В этом случае ошибка MySQL 1172 - результат, состоящий из более чем одной строки из-за двух или более имен Player_, добавляется к переменной. Может кто-нибудь, пожалуйста, дать мне представление о том, как это решить?

+0

Просьба представить структуру таблицы. Похоже, у вас конфликты индексов. – cyadvert

+0

В случае, когда у 2 игроков одинаковый счет Завоевателя, как бы вы наградили очки? То же самое для обоих, а затем пропустить следующего человека? Или что-то другое? – Matt

+0

Это только одна таблица с несколькими столбцами, на ней нет указателей. Имя игрока VARCHAR (50) | Завоеватель INT | Wall_Breaker INT | Unbreakable INT – Voodoo

ответ

0

Если вам не нужно размещать пользователь с одинаковым Conqueror на то же место вы можете использовать этот один запрос :-) не 5.

обновленного запроса уже позволяют пользователям иметь те же Conqueror и они получат такое же количество очков в соответствии с вашим комментарием:

В идеале, допустим, игрок с номером 2 и 3 имеет одинаковую оценку. Игрок 2 получает 4 очка, а игрок 3 также 4 очка, но игрок 4 получает вознаграждение в 2 очка. Таким образом, когда есть одинаковые оценки, все игроки получают очки, как если бы они были единственными, у кого этот счет. - Voodoo

SET @rank = 6; 
UPDATE Player 
INNER JOIN 
(
    SELECT player_id, 
    @rank := @rank-1 as rank, 
    CASE WHEN @prev = Conqueror 
     THEN @correction := @correction+1 
     ELSE @correction := 0 
    END as correction, 
    @prev := Conqueror 
    FROM Player 
    ORDER BY Conqueror DESC 
    LIMIT 5 
) as r 
ON Player.player_id = r.player_id 
SET Points = Points + r.rank + r.correction; 

И если вам нужно разместить игрок с тем же Conqueror результатом на то же звание, просто дайте мне несколько правил, как обращаться с такими ситуациями.

EDIT - ОБЪЯСНЕНИЕ

Cauze вы прокомментировали вы не понимаете, что происходит в моем запросе, я попытаюсь объяснить немного.

So @prev var хранит значение предыдущего верхнего игрока.

Например, для игрока, имеющего 2-й ранг, он удерживает значение Conqueror 1-го игрока.

Нам нужно его сравнить, если игрок 2-го места имеет тот же счет, что и 1-й, чтобы дать ему столько же очков, сколько вы просили в своем комментарии.

и r.correction содержит RANK (очки/место от 5 до 1) для игрока, которого вы хотите добавить в поле Points. И коррекция означает правильное значение, если игроки имеют одинаковые Conqueror, и нам нужно дать такое же количество очков, даже если ранжирование равно 2 и 3, но добавленные очки будут одинаковыми. rank = 4 + correction = 0 для 2-го игрок и ранг = 3 + коррекция = 1 для третьего игрока

+0

Я не понимаю, что такое @prev и как вы можете войти в CASE КОГДА, прежде чем ему присваивается значение. Также, что вы имели в виду от Player.id, должен ли я сделать дополнительный столбец с идентификаторами игроков, также я не знаю, что вы имеете в виду с r.rank или r.correction в конце запроса. Спасибо за ответ, но я действительно этого не понимаю. – Voodoo

+0

@Voodoo hmmm. у вас нет столбца 'player.id'? поэтому ваш уникальный индекс для игрока - 'Player_name'? – Alex

+0

Я добавил player_id, auto increment, и теперь это уникальный первичный ключ. Не могли бы вы немного объяснить, как работает ваш код? – Voodoo

0

Я не успел поиграть с ним и придумал решение, в котором игрок 4 получает 2 очка вместо 3, но это, вероятно, просто случай добавления дополнительного бита в оператор IF. Но, основываясь на этом блоге:

http://jimmod.com/blog/2008/09/09/displaying-row-number-rownum-in-mysql/

Я бы на самом деле избавиться от хранимой процедуры и сделать все это в одном заявлении обновления с подвыборкой. Что-то вроде (полностью непроверенной!):

update Player set points = 
    (select points from 
     (SELECT @rownum:[email protected] 'points', Conqueror FROM Player p, 
      (SELECT @rownum:=6) r 
     order by Conqueror desc 
    ) 
) 

Это должно, если я угадал правильный синтаксис, выделяют 5 к высшим, 4 ко второму, и т.д., за исключением, если два игрока имеют одинаковое количество очков, одна воля получить 4, а другой получит 3. Проверьте сообщение в блоге для оператора IF, который будет решить эту проблему - я посмотрю позже, когда у меня больше времени :)

EDIT

В случае с блог когда-либо снимается, это заявление IF я имею в виду:

select IF(@score=p.score, @rownum, @rownum:[email protected]+1) rank2, p.*, (@score:=p.score) dummy from player p, 
(SELECT @rownum:=0) x, 
(SELECT @score:=0) y 
order by score desc limit 10; 
Смежные вопросы