使用Bigquery(标准SQL)获取每组分组结果的前n条记录

时间:2017-06-21 15:33:51

标签: sql google-bigquery

我见过this question,这几乎就是我想要的。但我无法使用标准SQL来使用Bigquery,因为BQ不允许用户定义的变量。

注意 - 我有任意数量的群组,因此根据链接问题中的第一个答案UNION所有群组都是不可行的。

  

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

     

给出如下表格,包含人,组和年龄列,   你会如何得到每组中最老的2个人? (在内   小组不应该产生更多的结果,但是给出前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  |
+--------+-------+-----+

链接问题中的一个答案提及使用ROW_NUMBER确实存在,但我无法确定如何重新启动每个组的数字。

2 个答案:

答案 0 :(得分:4)

这是row_number()

select t.*
from (select t.*,
             row_number() over (partition by group order by age desc) as seqnum
      from t
     ) t
where seqnum <= 2;

row_number()是ANSI标准窗口函数。它在大多数数据库中都可用。一般来说,我建议您使用Postgres而不是MySQL来寻找解决BQ问题的解决方案(如果您无法自己找到BQ资源)。

答案 1 :(得分:4)

您可以使用ARRAY_AGG限制。例如,

#standardSQL
SELECT
  `Group`,
  ARRAY_AGG(STRUCT(Person, Age)
            ORDER BY Age DESC LIMIT 2) AS oldest_people
FROM People
GROUP BY `Group`;