SQL Server中Group By排除Val=0值的最优实现方案问询
解决按指定列分组但保留特定值行的SQL需求
嘿,我来帮你搞定这个需求!先明确下我们的场景:
原始数据
| ID | Val | Amount |
|---|---|---|
| 1 | 0 | 3 |
| 2 | 0 | 3 |
| 3 | 0 | 4 |
| 4 | 1 | 2 |
| 5 | 1 | 3 |
| 6 | 2 | 3 |
| 7 | 2 | 4 |
需求目标
对Val列分组计算Amount的总和,但Val=0的记录保持原样不聚合,最终得到如下结果:
| Val | Amount |
|---|---|
| 0 | 3 |
| 0 | 3 |
| 0 | 4 |
| 1 | 5 |
| 2 | 7 |
最优解法:用动态分组键实现一次扫描
你提到的UNION方法需要两次扫描数据(一次取Val=0的行,一次分组聚合Val≠0的行),其实我们可以通过设计一个动态分组键,让SQL一次扫描就能完成需求,性能更优:
SELECT Val, SUM(Amount) AS Amount FROM your_table_name GROUP BY Val, CASE WHEN Val = 0 THEN ID ELSE 0 END;
原理说明
- 当
Val=0时,分组键是Val + ID(因为每个ID唯一,所以每个Val=0的行会单独成为一个分组,SUM(Amount)就是它自己的数值) - 当
Val≠0时,分组键是Val + 0,也就是所有同Val的行会被分到同一组,SUM(Amount)就会计算该组的总和
这样就完美实现了需求,不需要UNION拼接结果集,只需要一次分组聚合操作,效率更高。
验证结果
执行上面的SQL后,得到的结果正好符合你的期望:
- Val=0的三行各自保留原始Amount值
- Val=1的两行总和为5,Val=2的两行总和为7
内容的提问来源于stack exchange,提问作者Zafer Sernikli
相关产品推荐
相关产品推荐

