按 select 个结果组添加排名列

Add Rank column by select result group

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

-----------------------------------------
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

我想要一个允许我有一个排名列的请求,我将在每个测试中获得每个参与者的排名,如下面的 table。

-----------------------------------------------
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;

但这行不通,我的排名是降序排列的,我的意思是分数最低的排名是 1,等等...比如:

-----------------------------------------------
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
---------------------------------------------

有人可以帮忙吗?

提前致谢

试试这个版本:

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 中表达式的求值顺序。所以,你不知道哪个先发生。

并且,MySQLv8+ 最终不再需要使用变量。它与 SQL 社区的其他成员一起支持 window 功能。这将逻辑简化为:

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

我现在想添加其他 3 列:

  • Max,其中包含每个组的最大分数,
  • Min 包含每组的最小分数,
  • 和包含每组平均分数的平均值

像这样 table 显示在这里:

------------------------------------------------------------------------
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;

但是我得到这个错误:

Can't reopen table

我认为这是由于 table myTable 是一个临时的 table。

你有什么想法吗?

谢谢