通过多个类别对表格进行排名

时间:2019-07-13 11:59:10

标签: mysql sql ranking rank

我正在尝试找到一种方法,可以通过多个类别对人们的分数进行排名。 该表包含每个玩家的列表以及他们参加的事件和得分。

查询需要根据每个事件中的得分为每个玩家分配等级。 (在事件1和事件2中分配的等级应该完全分开。)

如果某个事件中缺少玩家,则应为他们分配(该类别中的玩家总数+ 1)的排名

我可以对1个类别进行基本排名。很简单但是我什至不知道该怎么做。

表中的数据

+--------+-------+---------+
| Name   | Score | Event # |
+--------+-------+---------+
| Kevin  | 73    | Event 1 |
| George | 69    | Event 1 |
| Henry  | 70    | Event 1 |
|        |       |         |
| George | 45    | Event 2 |
| Kevin  | 65    | Event 2 |
| Henry  | 65    | Event 2 |
| Daniel | 50    | Event 2 |
+--------+-------+---------+

预期回报

+---------+--------+------+
| Event # | Name   | Rank |
+---------+--------+------+
| Event 1 | Kevin  | 1    |
| Event 1 | Henry  | 2    |
| Event 1 | George | 3    |
| Event 1 | Daniel | 4    |
| Event 2 | Kevin  | 1    |
| Event 2 | Henry  | 1    |
| Event 2 | Daniel | 3    |
| Event 2 | George | 4    |
+---------+--------+------+

请注意,排名并不密集! 我使用的是MySql 5.7。

实际上,我有50多个活动和数百人。

这是我排名1项赛事的条件

SELECT
        IF( SCORE =@_last_rank,@curRank:=@curRank,@curRank:=@_sequence) AS RANK,
        NAME,
        EVENT,
        @_sequence:=@_sequence+1,@_last_rank:= SCORE
        FROM (SELECT * FROM database WHERE EVENT = $event) p, 
        (SELECT @curRank := 1, @_sequence:=1, @_last_rank:=0) r
        ORDER BY  RANK, NAME

2 个答案:

答案 0 :(得分:0)

此sql语句

Select eventno,Name,rank 
From 
 (Select eventno,Name,
            CASE 
              WHEN @event = eventno THEN @rownum := @rownum + 1
              ELSE 
                  @rownum := 1
             END as rank,
             @event := eventno
      From table1 t
      JOIN (SELECT @rownum := 0) r
      JOIN (SELECT @event := (Select Eventno from table1 Limit 1)) s
  ORDER BY t.eventno,t.score) x;


  CREATE TABLE table1
  (`Name` varchar(6), `Score` int, `Eventno` varchar(7)) 

  INSERT INTO table1
(`Name`, `Score`, `Eventno`)
VALUES
('Kevin', 73, 'Event 1'),
('George', 69, 'Event 1'),
('Henry', 70, 'Event 1'),
('George', 45, 'Event 2'),
('Kevin', 65, 'Event 2'),
('Henry', 65, 'Event 2'),
('Daniel', 50, 'Event 2')

给出以下结果:

  eventno   Name    rank
  Event 1   George  1
  Event 1   Henry   2
  Event 1   Kevin   3
  Event 2   George  1
  Event 2   Daniel  2
  Event 2   Kevin   3
  Event 2   Henry   4
  7 rows

答案 1 :(得分:0)

以下方法避免了(不可靠的)使用用户变量和高度复杂的查询。它使用临时表并利用MyISAM的每组自动输入功能,以每组生成行号。为了从行号中获得排名,使用了带有MIN(row_number)的GROUP BY查询。

drop temporary table if exists tmp_scores;
create temporary table tmp_scores(
  rn int auto_increment,
  event varchar(50),
  name varchar(50),
  score int,
  primary key (event, rn)
)engine=myisam;

insert into tmp_scores(event, name, score)
  select e.event, n.name, t.score
  from (select distinct t.event from mytable t) e
  cross join (select distinct t.name from mytable t) n
  left join mytable t on t.event = e.event and t.name = n.name
  order by e.event, t.score is null, t.score desc;

drop temporary table if exists tmp_rank_by_score;
create temporary table tmp_rank_by_score(
  event varchar(50),
  score int,
  rank int,
  primary key (event, rank)
)engine=myisam;

insert into tmp_rank_by_score(event, score, rank)
  select event, score, min(rn) as rank
  from tmp_scores
  group by event, score;

select s.event, s.name, s.score, r.rank
from tmp_scores s
join tmp_rank_by_score r on r.event = s.event and r.score <=> s.score
order by r.event, r.rank;

drop temporary table if exists tmp_rank_by_score;
drop temporary table if exists tmp_scores;

结果:

| event   | name   | score | rank |
| ------- | ------ | ----- | ---- |
| Event 1 | Kevin  | 73    | 1    |
| Event 1 | Henry  | 70    | 2    |
| Event 1 | George | 69    | 3    |
| Event 1 | Daniel |       | 4    |
| Event 2 | Kevin  | 65    | 1    |
| Event 2 | Henry  | 65    | 1    |
| Event 2 | Daniel | 50    | 3    |
| Event 2 | George | 45    | 4    |

db-fiddle