Bigquery:按分组条件选择前3名

时间:2018-12-06 08:52:17

标签: sql google-bigquery

我有一张这样的桌子

type    Total
 A       100
 A       123
 A       154
 A       50
 A       54
 B       200
 B       166
 B       423
 B       342
 B       213
 C       520
 C       130
 C       234
 C       512

我想按组选择前3名。我该怎么办?

3 个答案:

答案 0 :(得分:2)

您可以尝试使用row_number()

select * from
(
select type, total, row_number() over(partition by type order by total desc) as rn
from tablename
)A
where rn<=3

答案 1 :(得分:2)

行数很好。在BigQuery中执行此操作的一种有趣方法是:

select type,
       array_agg(total order by total desc limit 3) as top3
from t
group by type;

这会将值放入数组。

答案 2 :(得分:2)

在大多数[大数据]使用案例中,使用ROW_NUMBER()效果不佳,因为最终会出现资源超过错误。这是因为它要求同一组的所有点都存在于相同/一个节点中,这在数据偏斜的情况下会导致BigQuery中上述错误

  

选项1

解决此问题的常用方法之一是使用ARRAY_AGG()函数,如下面的示例所示

#standardSQL
SELECT type, total FROM (
  SELECT type, ARRAY_AGG(total ORDER BY total DESC LIMIT 3) arr
  FROM `project.dataset.table` GROUP BY type
), UNNEST(arr) total

如果要针对您问题中的数据示例运行

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 'A' type, 100 total UNION ALL
  SELECT 'A', 123 UNION ALL
  SELECT 'A', 154 UNION ALL
  SELECT 'A', 50 UNION ALL
  SELECT 'A', 54 UNION ALL
  SELECT 'B', 200 UNION ALL
  SELECT 'B', 166 UNION ALL
  SELECT 'B', 423 UNION ALL
  SELECT 'B', 342 UNION ALL
  SELECT 'B', 213 UNION ALL
  SELECT 'C', 520 UNION ALL
  SELECT 'C', 130 UNION ALL
  SELECT 'C', 234 UNION ALL
  SELECT 'C', 512 
)
SELECT type, total FROM (
  SELECT type, ARRAY_AGG(total ORDER BY total DESC LIMIT 3) arr
  FROM `project.dataset.table` GROUP BY type
), UNNEST(arr) total
-- ORDER BY type   

您将获得预期的结果

Row type    total    
1   A       154  
2   A       123  
3   A       100  
4   B       423  
5   B       342  
6   B       213  
7   C       520  
8   C       512  
9   C       234    
  

选项2

但是要考虑真正的大数据,还有另一个有趣的选择-使用APPROX_TOP_SUM()函数,如下例所示

#standardSQL
SELECT type, value AS total FROM (
  SELECT type, APPROX_TOP_SUM(total, total, 3) arr
  FROM `project.dataset.table` GROUP BY type
), UNNEST(arr)  

显然,对于示例数据,其输出与上述相同