且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

获取每组分组结果的前 n 条记录

更新时间:2022-10-18 09:15:20

这是一种方法,使用 UNION ALL(参见 SQL Fiddle with Demo).这适用于两个组,如果您有两个以上的组,则需要指定 group 编号并为每个 group 添加查询:

(选择 *来自 mytable其中`组`= 1按年龄排序限制 2)联合所有(选择 *来自 mytable其中`组`= 2按年龄排序限制 2)

有多种方法可以做到这一点,请参阅本文以确定适合您情况的***路线:

http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/

这也可能对您有用,它为每条记录生成一个行号.使用上面链接中的示例,这将仅返回行数小于或等于 2 的那些记录:

选择人物,`group`,年龄从(选择人、组"、年龄、(@num:=if(@group = `group`, @num +1, if(@group := `group`, 1, 1))) row_number从测试 t交叉连接(选择@num:=0,@group:=null)c按组"、年龄、人排序) 作为 x其中 x.row_number 

参见演示

The following is the simplest possible example, though any solution should be able to scale to however many n top results are needed:

Given a table like that below, with person, group, and age columns, how would you get the 2 oldest people in each group? (Ties within groups should not yield more results, but give the first 2 in alphabetical order)

+--------+-------+-----+
| Person | Group | Age |
+--------+-------+-----+
| Bob    | 1     | 32  |
| Jill   | 1     | 34  |
| Shawn  | 1     | 42  |
| Jake   | 2     | 29  |
| Paul   | 2     | 36  |
| Laura  | 2     | 39  |
+--------+-------+-----+

Desired result set:

+--------+-------+-----+
| Shawn  | 1     | 42  |
| Jill   | 1     | 34  |
| Laura  | 2     | 39  |
| Paul   | 2     | 36  |
+--------+-------+-----+


NOTE: This question builds on a previous one- Get records with max value for each group of grouped SQL results - for getting a single top row from each group, and which received a great MySQL-specific answer from @Bohemian:

select * 
from (select * from mytable order by `Group`, Age desc, Person) x
group by `Group`

Would love to be able to build off this, though I don't see how.

Here is one way to do this, using UNION ALL (See SQL Fiddle with Demo). This works with two groups, if you have more than two groups, then you would need to specify the group number and add queries for each group:

(
  select *
  from mytable 
  where `group` = 1
  order by age desc
  LIMIT 2
)
UNION ALL
(
  select *
  from mytable 
  where `group` = 2
  order by age desc
  LIMIT 2
)

There are a variety of ways to do this, see this article to determine the best route for your situation:

http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/

Edit:

This might work for you too, it generates a row number for each record. Using an example from the link above this will return only those records with a row number of less than or equal to 2:

select person, `group`, age
from 
(
   select person, `group`, age,
      (@num:=if(@group = `group`, @num +1, if(@group := `group`, 1, 1))) row_number 
  from test t
  CROSS JOIN (select @num:=0, @group:=null) c
  order by `Group`, Age desc, person
) as x 
where x.row_number <= 2;

See Demo