Сложный ранговый запрос MySQL со связями

Допустим, у меня была следующая таблица:

id | name | points  
-------------------
1  | joe  | 100  
2  | bob  | 95  
3  | max  | 95  
4  | leo  | 90

Могу ли я создать набор записей с обратным рангом, например:

id | name | points | rank  
--------------------------
4  | leo  | 90     | 1  
3  | max  | 95     | 2.5  
2  | bob  | 95     | 2.5   
1  | joe  | 100    | 4  

person voldomazta    schedule 31.01.2011    source источник


Ответы (2)


Это полностью рабочий пример с этой таблицей примеров

create table tpoints (id int, name varchar(10), points int);
insert tpoints values
(1  ,'joe', 100 ),
(2  ,'bob', 95  ),
(3  ,'max', 95  ),
(4  ,'leo', 90  );

Запрос MySQL

select t.*, sq.`rank`
from
(
    select
       points,
        @rank := case when @g = points then @rank else @rn + (c-1)/2.0 end `rank`,
       @g := points,
       @rn := @rn + c
    from 
       (select @g:=null, @rn:=1) g,
        (select points, count(*) c
        from tpoints
        group by points
        order by points asc) p
) sq inner join tpoints t on t.points = sq.points
order by t.points asc;

Он также имеет то преимущество, что работает очень хорошо по сравнению с выполнением коррелированного перекрестного (само) соединения.

  • 1x пройти через tpoints для объединения в группы
  • расчет ранга с учетом связей
  • 1x присоединитесь к таблице, чтобы поставить ранги против рекордов.
person RichardTheKiwi    schedule 31.01.2011
comment
отлично - если это работает, поставьте галочку рядом с ответом, чтобы принять его. Благодарность - person RichardTheKiwi; 31.01.2011
comment
Это вернет x.5 для любого количества x дубликатов. Если есть три дубликата, скажем, 9, все они будут 9,5, а не 9,333.... Также можно сделать без самосоединения. - person OMG Ponies; 31.01.2011
comment
требование состоит в том, что когда некоторые записи имеют одинаковый ранг, вы суммируете количество этих рангов и делите их на количество записей, связанных с этим рангом, что кибервики отлично усвоила. также спасибо OMG Ponies за то, что нашли время ответить. - person voldomazta; 31.01.2011
comment
@omg - This will return x.5 for any number of "x" duplicates. If there's three duplicates of say "9", they'll all be "9.5" rather than "9.333...". И вы подтвердили это, потратив 2 минуты на проверку? Could also be done without the self join. - хотелось бы посмотреть, как это делается; Я могу еще научиться некоторым трюкам от вас, если вы не против поделиться. - person RichardTheKiwi; 31.01.2011

Не будет "2,5" в качестве значения ранга, но дубликаты будут иметь тот же номер, если вы используете:

  SELECT x.id, 
         x.name,
         x.points,
         (SELECT COUNT(*)
            FROM YOUR_TABLE y
           WHERE y.points <= x.points) AS rank
    FROM YOUR_TABLE x
ORDER BY x.points 
person Community    schedule 31.01.2011
comment
Если он не даст ответа, зачем его излагать? - person RichardTheKiwi; 31.01.2011
comment
Не уверен, что не является ответом, когда предоставляется функционирующий запрос, требования признаются, но оставляются на усмотрение ОП для дальнейшего уточнения. - person OMG Ponies; 31.01.2011