在BigQuery中按所有者和流派分组返回各前20条数据样本
更高效的按Owner+Genre分组取前20条样本的方案
嘿,你现在用一堆UNION ALL拼接查询的方式确实太笨重了——不仅写起来麻烦,数据库还得重复扫描整张表N次,性能开销会随着Owner和Genre组合的增多直线上升。我之前也踩过类似的坑,给你推荐个更简洁高效的方案:用窗口函数实现分组内的Top N筛选。
核心思路
利用ROW_NUMBER()窗口函数,按Owner和Genre作为分组键(PARTITION BY),给每个分组内的记录编号,最后只保留编号≤20的记录即可。这样数据库只需要扫描一次表,就能完成所有分组的Top N筛选。
具体SQL示例
SELECT Owner, Genre, Data_one, Data_two FROM ( SELECT Owner, Genre, Data_one, Data_two, -- 按Owner和Genre分组,每组内按你需要的规则排序(比如创建时间、评分等) ROW_NUMBER() OVER ( PARTITION BY Owner, Genre ORDER BY create_time DESC -- 这里替换成你实际需要的排序字段,确保取到的是你想要的前20条 ) AS row_num FROM `dataset-table` -- 如果需要过滤特定的Genre或Owner,在这里加WHERE条件即可,比如: -- WHERE Genre LIKE "%HORROR%" OR Owner = "Alex" ) ranked_records WHERE row_num <= 20;
方案优势
- 性能更优:仅需扫描一次表,避免了
UNION ALL方案中多次重复扫描的开销,数据量越大,优势越明显 - 维护简单:不需要手动拼接几十上百个查询块,不管有多少Owner和Genre组合,都能自动覆盖
- 灵活性高:可以通过调整
ORDER BY子句,灵活控制每组内取哪些记录(比如最新的20条、评分最高的20条等)
额外说明
如果你业务上允许同组内出现并列排名的记录(比如同Owner同Genre下有20条以上相同优先级的记录,想全部保留),可以把ROW_NUMBER()换成RANK()或DENSE_RANK():
RANK():会跳过并列的编号(比如1,1,3)DENSE_RANK():不会跳过编号(比如1,1,2)
根据你的实际业务需求选择就行。
内容的提问来源于stack exchange,提问作者Quirke1337
相关产品推荐
相关产品推荐

