Key*_*Jun 5 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
Run Code Online (Sandbox Code Playgroud)
我想按组选择总计前 3 名。我该怎么做?
行号就好。在 BigQuery 中执行此操作的一种有趣方法是:
select type,
array_agg(total order by total desc limit 3) as top3
from t
group by type;
Run Code Online (Sandbox Code Playgroud)
这会将值放入数组中。
在大多数[大数据]用例中,使用 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
Run Code Online (Sandbox Code Playgroud)
如果要针对您的问题中的数据示例运行上面的代码
#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
Run Code Online (Sandbox Code Playgroud)
你会得到预期的结果
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
Run Code Online (Sandbox Code Playgroud)
选项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)
Run Code Online (Sandbox Code Playgroud)
显然,样本数据的输出与上面相同
您可以尝试使用 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
Run Code Online (Sandbox Code Playgroud)