Как получить ранг строки? - PullRequest
8 голосов
/ 18 марта 2011

HI

Я вчера опубликовал похожий (или такой же?) Вопрос, но подумал, что мне нужно опубликовать новый вопрос, поскольку у меня короткий, но понятный вопрос.

У меня есть следующая таблица.

id  point
1   30
2   30
3   29
4   27
5   28
6   26

что я хочу:

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

  2. Я хочу запросить рейтинг по идентификатору пользователя. Мне нравится получать 1 как результат моего ранга, когда я опрашиваю пользователей # 1 и # 2, потому что у них обоих есть 30 баллов

Добавлено: 3/18

Я попробовал запрос Логана, но получил следующий результат

id point   rank
1   30  1
2   30  1
3   29  3
4   27  5
5   28  4
6   26  6

Ответы [ 5 ]

5 голосов
/ 18 марта 2011

Рекомендуемый подход к подзапросам будет масштабироваться квадратично. http://www.xaprb.com/blog/2006/12/02/how-to-number-rows-in-mysql/ показывает гораздо более эффективный подход с пользовательскими переменными. Вот непроверенная адаптация к вашей проблеме:

@points := -1; // Should be an impossible value.
@num := 0;

SELECT id
  , points
  , @num := if(@points = points, @num, @num + 1) as point_rank
  , @points := points as dummy
FROM `users`
ORDER BY points desc, id asc;
4 голосов
/ 18 марта 2011

Просто посчитайте, сколько людей набрали больше очков, чем они.

select count(1) from users 
where point > (select point from users where id = 2) group by point

Это даст вам количество людей, у которых больше очков для данного пользователя.Таким образом, для пользователя 1 и пользователя 2 результат будет 0 (ноль), что означает, что они первые.

2 голосов
/ 05 августа 2012

ОП хотел бы, чтобы номера рангов были пропущены, если их ранее были дублирующимися точками с таким же рангом.Например, ниже показано, как пропускается 2, потому что ранг 1. появляется дважды.

id  point  rank
1   30     1
2   30     1
3   29     3
4   27     4
5   28     5
6   26     6

Это может быть достигнуто путем изменения кода btilly следующим образом:

set @points := -1; // Should be an impossible value.
set @num := 0;
set @c := 1;
SELECT id
  , points
  , @num := if(@points = points, @num, @num + @c) as point_rank
  , @c := if(@points = points, @c+1, 1) as dummy
  , @points := points as dummy2
FROM `users`
ORDER BY points desc, id asc;
2 голосов
/ 18 марта 2011

Когда мне нужно было сделать что-то похожее, я создал вид, который выглядел так:

CREATE VIEW rankings_view 
AS 
SELECT id
,      point
,      (select count(1) 
          from points b
         where  b.point > a.point) +1 as rank
FROM points as a;

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

РЕДАКТИРОВАТЬ

Если вы хотите посчитать количество отдельных значений точек над каждым значением точки вместо количества записей с значениями точек выше текущего значения точки, вы можете сделать что-то вроде:

CREATE VIEW rankings_view2
AS 
SELECT id
,      point
,      (SELECT COUNT(1) +1 AS rank 
          FROM ( SELECT DISTINCT point
                   FROM points b
                  WHERE   b.point >a.point ))
FROM points AS a;

Примечание

Некоторые из представленных решений определенно работают лучше, чем это. Они специфичны для mysql, поэтому я не могу использовать их для того, что я делаю. Мое приложение имеет не более 128 объектов для ранжирования, поэтому для меня это достаточно хорошо. Однако, если у вас может быть множество строк, вы можете захотеть использовать одно из других решений, представленных здесь, или ограничить область ранжирования.

0 голосов
/ 18 марта 2011
SET @rank = 0, @prev_val = NULL;
SELECT id, @rank := IF(@prev_val=points,@rank,@rank+1) AS rank,
@prev_val := points AS points FROM users ORDER BY points DESC, id asc;

Таблица: пользователи

...