在SQL中,如何为每个组选择前2行

wai*_*kuo 15 mysql sql group-by greatest-n-per-group

我有一张表如下:

NAME    SCORE
-----------------
willy       1
willy       2
willy       3
zoe         4
zoe         5
zoe         6
Run Code Online (Sandbox Code Playgroud)

这是样本

聚合功能group by只允许我获得每个的最高分name.我想进行查询以获得每个最高的2分name,我该怎么办?

我的预期产量是

NAME    SCORE
-----------------
willy       2
willy       3
zoe         5
zoe         6
Run Code Online (Sandbox Code Playgroud)

Joh*_*Woo 20

SELECT *
FROM   test s
WHERE 
        (
            SELECT  COUNT(*) 
            FROM    test  f
            WHERE f.name = s.name AND 
                  f.score >= s.score
        ) <= 2
Run Code Online (Sandbox Code Playgroud)

  • 但这可能会导致性能问题。有没有其他更快的方法来实现这个查询? (3认同)
  • 这可以线性完成,请参阅http://www.sqlines.com/mysql/how-to/get_top_n_each_group的"MySQL查询获取前2名" (3认同)

Tar*_*ryn 11

在MySQL中,您可以使用用户定义的变量来获取每个组中的行号:

select name, score
from
(
  SELECT name,
    score,
    (@row:=if(@prev=name, @row +1, if(@prev:= name, 1, 1))) rn
  FROM test123 t
  CROSS JOIN (select @row:=0, @prev:=null) c
  order by name, score desc 
) src
where rn <= 2
order by name, score;
Run Code Online (Sandbox Code Playgroud)

演示


小智 8

如果您不介意有额外的列,那么您可以使用以下代码:

SELECT Name, Score, rank() over(partition by Name order by Score DESC) as rank
From Table
Having rank < 3;
Run Code Online (Sandbox Code Playgroud)

Rank 函数为每个分区提供排名,在您的情况下它是名称


小智 5

insert into test values('willy',1)
insert into test values('willy',2)
insert into test values('willy',3)
insert into test values('zoe',4)
insert into test values('zoe',5)
insert into test values('zoe',6)


;with temp_cte
as (
    select Name, Score,
       ROW_NUMBER() OVER (
          PARTITION BY Name
          ORDER BY Score desc
       ) row_num
    from test
)
select * from temp_cte
where row_num < 3
Run Code Online (Sandbox Code Playgroud)