SQL中基于两列交换等价分组的Partition Over求和问题
解决无序双字段分组求和的问题
我经常碰到这类需求——把两个字段的无序组合当成同一组来聚合,下面给你具体的实现方案:
原始数据
首先看你的原始表格:
| No1 | No2 | Amount |
|---|---|---|
| A | B | 10 |
| C | D | 20 |
| B | A | 30 |
| D | C | 40 |
你的需求是:将(No1,No2)和(No2,No1)视为同一分组,用窗口函数计算每组的金额总和,预期A-B和B-A的总和是40,C-D和D-C的总和是60。
核心思路
关键是生成统一的分组键——不管两个字段的顺序如何,让它们映射到同一个分组标识。大多数SQL数据库都支持LEAST()和GREATEST()函数,正好用来实现这个逻辑:
LEAST(No1, No2):返回两个值中较小的那个GREATEST(No1, No2):返回两个值中较大的那个
这样(A,B)和(B,A)都会生成(A,B)作为分组键,窗口函数就能正确聚合。
实现代码
通用版本(支持MySQL、PostgreSQL、SQL Server 2022+等)
SELECT No1, No2, SUM(Amount) OVER (PARTITION BY LEAST(No1, No2), GREATEST(No1, No2)) AS Sum_Amount FROM your_table;
兼容老版本数据库(比如SQL Server 2019及以前)
如果你的数据库不支持LEAST()/GREATEST(),可以用CASE语句替代:
SELECT No1, No2, SUM(Amount) OVER ( PARTITION BY CASE WHEN No1 < No2 THEN No1 ELSE No2 END, CASE WHEN No1 < No2 THEN No2 ELSE No1 END ) AS Sum_Amount FROM your_table;
预期结果
执行后会得到你想要的结果:
| No1 | No2 | Sum_Amount |
|---|---|---|
| A | B | 40 |
| C | D | 60 |
| B | A | 40 |
| D | C | 60 |
这样就完美实现了无序双字段的分组求和,不同数据库的语法细节可能略有不同,但核心逻辑都是统一分组键~
内容的提问来源于stack exchange,提问作者ZerOne
相关产品推荐
相关产品推荐

