MySQL各班前k名学生
我有两个看起来像这样的表:
Class Name Score Top
1 Amy 90 X
1 Ben 70 X
1 Chu 80 X
2 Don 60 X
2 Elf 65 X
2 Fez 75 X
2 Ges 35 X
2 Han 40 X
Class NumToppers
1 2
2 3
我想从每个类中找到排名靠前的“NumToppers”,并相应地更新“Top”字段:
Class Name Score Top
1 Amy 90 Y
1 Ben 70 N
1 Chu 80 Y
2 Don 60 Y
2 Elf 65 Y
2 Fez 75 Y
2 Ges 35 N
2 Han 40 N
我的真实数据中有数百个“类”。因此,尽管数据看起来很玩具,但请不要提供玩具解决方案。
I have two tables that looks like this:
Class Name Score Top
1 Amy 90 X
1 Ben 70 X
1 Chu 80 X
2 Don 60 X
2 Elf 65 X
2 Fez 75 X
2 Ges 35 X
2 Han 40 X
Class NumToppers
1 2
2 3
I want to find Top "NumToppers" from each class and accordingly update "Top" field:
Class Name Score Top
1 Amy 90 Y
1 Ben 70 N
1 Chu 80 Y
2 Don 60 Y
2 Elf 65 Y
2 Fez 75 Y
2 Ges 35 N
2 Han 40 N
I have 100s of "Classes" in my real data. So, although data looks toyish, no toy solutions please.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
参考 这个关于选择“每个组中最伟大的n个”的优秀页面,这是我提出的查询。回想起来,它与 @BassamMehanni 的答案基本相同,只是 MySQL 中没有
ROW_NUMBER()
函数。这假设您有表
class
和toppers
。解决方案:
注意:如果
class
表上的主 ID 不是复合(Class,Name,Score)
组合,请使用该主 ID 作为连接条件标记为#@@
。说明
基本上,此查询:
class
的行进行编号。也就是说,对每个班级中的每个学生进行排名。rank
为<= NumToppers
的class
行。对于第 1 步,请参阅以下内容(来自我向您推荐的链接):
这将查看
class
的每一行(之后按类别和降序分数排序)并设置rank
如果我们进入新班级,则为 1;如果我们在同一班级,则为rank+1
。对于第 2 步,我们在
class
上使用toppers
进行 JOIN,并为每个类选取顶部的NumToppers
行:最后,我们根据这些条件进行更新(步骤 3)。但是,我们必须显式执行
UPDATE class
,因此我们必须在步骤 2 中使用class
添加额外的JOIN
:如果您有主 ID在最好不是复合的类(即一列 ID)上,然后加入它。
Referring to this excellent page on selecting the 'greatest-n-per-group', here's the query I came up with. In retrospect it is basically identical to @BassamMehanni's answer, except that there is no
ROW_NUMBER()
function in MySQL.This assumes you have tables
class
andtoppers
.Solution:
Note: if you have a primary ID on the
class
table that isn't the compound(Class,Name,Score)
combination, use that instead for the join condition marked#@@
.Explanation
Basically, this query:
class
from top-to-bottom by score, within each class. That is, ranks each student within each class.class
for which therank
is<= NumToppers
, for each class.For step 1, see the following (from the link I referred you):
This looks through every row of
class
(after by sorting by class and descending score) and sets therank
to 1 if we're on to a new class, or torank+1
if we're within the same class.For step 2, we do a JOIN with
toppers
onclass
and pick the topNumToppers
rows for each class:Finally, we update on these conditions (step 3). However we have to do
UPDATE class
explicitly so we have to add in an extraJOIN
of step 2 withclass
:If you have a primary ID on
class
that is preferrably not compound (ie a one-column ID) then join on that instead.