按选择结果组添加排名列

时间:2018-06-12 10:57:08

标签: mysql sql group-by sql-order-by rank

我有一个名为myTable的表,其中包含每个测试中的参与者列表和他们的分数。

-----------------------------------------
id_test     id_paticipant   score
-----------------------------------------
id_test1    Partcipant1      100
id_test1    Partcipant2      200
id_test1    Partcipant3      150
id_test1    Partcipant4      300
id_test2    Partcipant1      500
id_test2    Partcipant3      250
id_test3    Partcipant2       70
id_test3    Partcipant3      150
id_test3    Partcipant4      420
id_test4    Partcipant1      120
id_test4    Partcipant2      200

我想要一个请求,允许我在每个测试中都有一个等级列表,如下表所示。

-----------------------------------------------
id_test     id_paticipant   score   rank
-------------------------------------------------------
id_test1    Partcipant1      100    4
id_test1    Partcipant2      200    2
id_test1    Partcipant3      150    3
id_test1    Partcipant4      300    1
id_test2    Partcipant1      500    1
id_test2    Partcipant3      250    2
id_test3    Partcipant2       70    3
id_test3    Partcipant3      150    2
id_test3    Partcipant4      420    1
id_test4    Partcipant1      120    2
id_test4    Partcipant2      200    1
---------------------------------------------

我试过这个:

SET @prev_id_test := 0;
SET @curRow := 1;
select t2.id_test, t2.id_partcipant, t2.score
,if(t2.id_test=@prev_id_test, @curRow := @curRow + 1, @curRow := 1) AS rank, @prev_id_test := t2.id_test 
from (select myTable.* from myTable order by myTable.id_test, myTable.score desc) as t2 
order by t2.id_test, t2.score, t2.id_partcipant desc;

但是它不起作用,我的排名降序,我的意思是得分最低的排名等等......如:

-----------------------------------------------
id_test     id_paticipant   score   rank
-----------------------------------------------
id_test1    Partcipant1      100    1
id_test1    Partcipant2      200    3
id_test1    Partcipant3      150    2
id_test1    Partcipant4      300    4
id_test2    Partcipant1      500    2
id_test2    Partcipant3      250    1
id_test3    Partcipant2       70    1
id_test3    Partcipant3      150    2
id_test3    Partcipant4      420    3
id_test4    Partcipant1      120    1
id_test4    Partcipant2      200    2
---------------------------------------------

有人可以帮忙吗?

提前致谢

2 个答案:

答案 0 :(得分:1)

试试这个版本:

select t.*,
       (@rn := if(@it = t.id_test, @rn + 1,
                  if(@it := t.id_test, 1, 1)
                 )
       ) as rank
from (select t.*
      from myTables t
      order by id_test, score desc
     ) t cross join
     (select @it := -1, @rn := 0) params;

有什么区别?您的版本正在分配变量并在不同的表达式中引用它们。 MySQL(也没有任何其他数据库)保证SELECT中表达式的评估顺序。所以,你不知道哪个先出现。

而且,MySQL v8 +终于使变量的使用变得不必要了。它已经加入了SQL社区的其他部分来支持窗口函数。这简化了以下逻辑:

row_number() over (partition by test_id order by score_desc) as ranking

答案 1 :(得分:0)

我现在想要添加3个其他列:

  • Max,其中包含每个组的最高分数,
  • Min,其中包含每组的最低分数,
  • 和包含每组平均得分的平均值

如下表所示:

------------------------------------------------------------------------
id_test     id_participant  score   rank    Max   Min   average
------------------------------------------------------------------------
id_test1    Partcipant1      100     4      300   100    187.5
id_test1    Partcipant2      200     2      300   100    187.5
id_test1    Partcipant3      150     3      300   100    187.5
id_test1    Partcipant4      300     1      300   100    187.5
id_test2    Partcipant1      500     1      500   250    375
id_test2    Partcipant3      250     2      500   250    375
id_test3    Partcipant2       70     3      420    70    213.33
id_test3    Partcipant3      150     2      420    70    213.33
id_test3    Partcipant4      420     1      420    70    213.33
id_test4    Partcipant1      120     2      200   120    160
id_test4    Partcipant2      200     1      200   120    160
------------------------------------------------------------------------

我试试这个:

select  
    t.*,
    (@rn := if(@it = t.id_test, @rn + 1,if(@it := t.id_test, 1, 1))) as rank,
    (select max(t1.score) from myTables t1 group by t1.id_test) as Max,
    (select min(t1.score) from myTables t1 group by t1.id_test) as Max,
    (select round((sum(t1.score)/count(t1.id_participant)), 2) from myTables t1 group by t1.id_test) as average
from
    (select t.* 
     from myTables 
     order by t.id_test, t.score desc) as t 
cross join 
    (select @it := -1, @rn := 0) params;

但是我收到了这个错误:

  

无法重新开启表格

我认为这是因为表myTable是一个临时表。

你有什么想法吗?

由于