如何拆分GROUP BY查询,将同一分组拆分为两组聚合结果?
问题描述
现有如下结构的数据表:
| Id 1 | Id 2 | Amount |
|---|---|---|
| 001 | AAA | 10 |
| 001 | AAA | 10 |
| 001 | AAA | 10 |
| 001 | AAA | 10 |
| 001 | AAA | 10 |
| 001 | AAA | 10 |
| 001 | AAA | 10 |
| 001 | AAA | 10 |
| 001 | AAA | 10 |
| 001 | AAA | 10 |
执行常规聚合查询:
SELECT id1, id2, sum(amount), count(*) FROM table GROUP BY id1, id2;
得到结果:
001 | AAA | 100 | 10
需求:将上述分组拆分为两组互斥的聚合结果,一组包含8条记录的总和与计数,另一组包含剩余2条的总和与计数,结果顺序无关。是否可以实现?
可以实现,以下是具体方案
核心思路是先给每条标记分组归属(区分8条和2条的集合),再基于标记字段做二次聚合。根据是否需要固定拆分,提供两种常用实现:
方案1:固定拆分(取任意8条+剩余2条)
用窗口函数生成行号,通过行号范围区分两组:
WITH numbered_records AS ( SELECT id1, id2, amount, -- 生成组内行号,不指定排序规则则按数据库默认存储顺序取数 ROW_NUMBER() OVER (PARTITION BY id1, id2 ORDER BY (SELECT NULL)) AS row_num FROM your_table_name ) SELECT id1, id2, CASE WHEN row_num <= 8 THEN '组1(8条)' ELSE '组2(2条)' END AS group_label, SUM(amount) AS total_amount, COUNT(*) AS record_count FROM numbered_records GROUP BY id1, id2, group_label;
执行后会返回两行结果,分别对应8条和2条记录的聚合值。
方案2:随机拆分(每次分配的记录可能不同)
如果需要随机挑选8条和2条,用随机函数标记分组:
WITH random_grouped_records AS ( SELECT id1, id2, amount, CASE WHEN RAND() <= 0.8 THEN '组1(随机8条)' ELSE '组2(随机2条)' END AS group_label FROM your_table_name ) SELECT id1, id2, group_label, SUM(amount) AS total_amount, COUNT(*) AS record_count FROM random_grouped_records GROUP BY id1, id2, group_label;
注意
- 不同数据库的随机函数语法有差异:比如SQL Server用
NEWID()实现随机排序,Oracle用DBMS_RANDOM.VALUE(),需要根据实际使用的数据库调整。 - 随机性会导致每次执行的具体分配记录不同,但整体会趋近于8条和2条的聚合结果。
内容的提问来源于stack exchange,提问作者AlbinA
相关产品推荐
相关产品推荐

