2014-09-12 3 views
1

Я хочу получить рейтинг игроков в игровой системе, но я не могу получить право работать с переменной @rank. Где проблема здесь?MySQL row_number с переменной ранга не работает

Первая таблица: 'игрок'

+----+----------+--------+ 
| id | name  | points | 
+----+----------+--------+ 
| 1 | Player 1 | 100 | 
| 2 | Player 2 | 250 | 
| 3 | Player 3 | 57 | 
| 4 | Player 4 | 578 | 
| 5 | Player 5 | 12580 | 
+----+----------+--------+ 

Вторая таблица: 'гильдия'

+----+------------+ 
| id | name  | 
+----+------------+ 
| 1 | FirstClass | 
+----+------------+ 

Третий стол: 'guild_player_cross'

+----+----------+-----------+ 
| id | guild_fk | player_fk | 
+----+----------+-----------+ 
| 1 | 1  | 2   | 
+----+----------+-----------+ 

Теперь я хочу, чтобы получить игроков рейтинг отсортирован по их точкам.

Запрос Заявление:

SELECT 
    @rank := @rank + 1 AS rank, 
    p.name, 
    p.points, 
    g.name AS guild 
FROM player AS p 
LEFT JOIN guild_player_cross AS gp ON p.id = gp.player_fk 
LEFT JOIN guild AS g ON gp.guild_fk = g.id 
INNER JOIN (
    SELECT @rank := 0 
) AS tblRank 
ORDER BY p.points DESC 

Но результат не в том, что я думал, потому что рейтинг число не корректны. :/

Результат:

+------+----------+--------+-------------+ 
| rank | name  | points | guild  | 
+------+----------+--------+-------------+ 
| 5 | Player 5 | 12580 | NULL  | 
+------+----------+--------+-------------+ 
| 4 | Player 4 | 578 | NULL  | 
+------+----------+--------+-------------+ 
| 1 | Player 2 | 250 | FirstClass | 
+------+----------+--------+-------------+ 
| 2 | Player 1 | 100 | NULL  | 
+------+----------+--------+-------------+ 
| 3 | Player 3 | 57 | NULL  | 
+------+----------+--------+-------------+ 

ответ

0

Вы можете попробовать этот запрос:

SELECT 
    @rank := @rank + 1, 
    p.name, 
    p.points, 
    ( 
     SELECT g.name 
     FROM guild_player_cross AS gp 
     LEFT JOIN guild AS g ON gp.guild_fk = g.id 
     WHERE p.id = gp.player_fk 
    ) AS guild 
FROM player AS p 
INNER JOIN (
    SELECT @rank := 0 
) AS tblRank 
ORDER BY p.points DESC; 

Я поставил объединятся в подзапроса не вмешиваться в порядок.

Я надеюсь, что вы полезны

1

Сортировка выполняется после того, как был добавлен ранг,

Попробуйте это:

SELECT 
    @rank := @rank + 1 AS rank, 
    x.* 
FROM (
SELECT 
    p.name, 
    p.points, 
    g.name AS guild 
FROM player AS p 
LEFT JOIN guild_player_cross AS gp ON p.id = gp.player_fk 
LEFT JOIN guild AS g ON gp.guild_fk = g.id 
INNER JOIN (
    SELECT @rank := 0 
) AS tblRank 
ORDER BY p.points DESC) x 
0

Вот альтернативный способ без переменных. Это будет предлагать более высокую производительность во многих случаях, когда есть много вещей для ранжирования.

SELECT FIND_IN_SET(points, points_list) AS rank, p.name, p.points, g.name AS guild 
FROM player AS p 
CROSS JOIN (SELECT GROUP_CONCAT(DISTINCT points ORDER BY points DESC) AS points_list FROM player) points_list 
LEFT JOIN guild_player_cross AS gp ON p.id = gp.player_fk 
LEFT JOIN guild AS g ON gp.guild_fk = g.id 
ORDER BY rank 
+0

Интересное решение. Не уверен в производительности (у меня будет игра с ним). Возможная проблема заключается в том, что у нескольких игроков одинаковый балл. Ваш DISTINCT сделает их обоих ранжированными одинаковыми и без пробелов после этого, но удаление DISTINCT приведет к тому, что оба они будут одинаковыми, но с разрывом в рейтинге впоследствии. – Kickstart

+0

Быстрая игра в существующую таблицу У меня есть записи ~ 290k. Решение, основанное на вашей идее, занимает ~ 8 секунд, а решение, основанное на переменной, занимает ~ 5 секунд. Интересно. Одной из потенциальных проблем является максимальная длина результата GROUP_CONCAT (по умолчанию - 1024). – Kickstart

+0

@kickstart, ваш пробег может отличаться; это альтернатива, которая может быть лучше, но, вероятно, требует некоторой дополнительной осторожности - по крайней мере, индекс для столбца, который должен быть оценен. – Lunc

Смежные вопросы