提问者:小点点

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


以下是最简单的示例,尽管任何解决方案都应该能够扩展到需要多少n个top结果:

给定一个像下面这样的表格,有个人、团体和年龄列,你如何得到每组中最老的两个人?(组内的联系不应该产生更多的结果,而是按照字母顺序给出前2个)

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

期望结果集:

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

注意:这个问题建立在前一个问题的基础上——为每组分组的SQL结果获取最大值的记录——用于从每个组中获取一个最上面的行,并从@Bohemian获得了一个非常好的MySQL特定答案:

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

我很想能够以此为基础,尽管我不知道该怎么做。


共3个答案

匿名用户

这里有一种方法可以做到这一点,使用UNION-ALL(参见SQLFiddle-with-Demo)。这适用于两个组,如果您有两个以上的组,则需要指定编号,并为每个添加查询:

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

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

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

编辑:

这可能也适用于您,它为每个记录生成行号。使用上面链接中的示例,这将只返回行数小于或等于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;

见演示

匿名用户

在其他数据库中,您可以使用行号执行此操作。MySQL不支持行数,但您可以使用变量来模拟它:

SELECT
    person,
    groupname,
    age
FROM
(
    SELECT
        person,
        groupname,
        age,
        @rn := IF(@prev = groupname, @rn + 1, 1) AS rn,
        @prev := groupname
    FROM mytable
    JOIN (SELECT @prev := NULL, @rn := 0) AS vars
    ORDER BY groupname, age DESC, person
) AS T1
WHERE rn <= 2

在线查看:sqlfiddle

编辑我刚刚注意到蓝脚报上了一个非常相似的答案:1给他。然而,这个答案有两个小优点:

  1. 这是一个单一的查询。变量在SELECT语句中初始化

所以我会把它留在这里,以防它能帮助别人。

匿名用户

试试这个:

SELECT a.person, a.group, a.age FROM person AS a WHERE 
(SELECT COUNT(*) FROM person AS b 
WHERE b.group = a.group AND b.age >= a.age) <= 2 
ORDER BY a.group ASC, a.age DESC

演示