SQL技术问询:基于两列分区并插入汇总值行
SQL:基于双向配对列分区并插入汇总行
我明白你的需求了——需要把No1和No2的双向配对(比如A-B和B-A)当成同一个分区,算出每组的总金额后插入汇总行对吧?下面给你详细的解决方案:
核心思路:统一分组标识
因为No1和No2的顺序不影响分组(A-B和B-A属于同一组),我们可以用LEAST()和GREATEST()函数生成一个固定顺序的分组键,确保所有双向配对都被归到同一组里。
第一步:验证分组汇总结果
先跑这段SQL确认分组汇总的逻辑是否符合预期:
SELECT LEAST(No1, No2) AS 分组左值, GREATEST(No1, No2) AS 分组右值, SUM(Amount) AS 组内总金额 FROM 你的数据表名 GROUP BY LEAST(No1, No2), GREATEST(No1, No2);
针对你给出的示例数据,这段会返回:
| 分组左值 | 分组右值 | 组内总金额 | |----------|----------|------------| | A | B | 40 | | C | D | 60 |
完全实现了A-B/B-A、C-D/D-C的双向配对汇总需求。
第二步:插入汇总行到数据表
接下来把这些汇总结果插入到原表中,这里提供两种常见写法,你可以根据需求选择:
写法1:汇总行标记为「汇总」便于区分
如果希望一眼就能识别出汇总行,可以给No1/No2设置特殊标识:
INSERT INTO 你的数据表名 (No1, No2, Amount, Timestamp) SELECT CONCAT('汇总_', LEAST(No1, No2), '-', GREATEST(No1, No2)) AS No1, '汇总' AS No2, SUM(Amount) AS Amount, CURRENT_TIMESTAMP AS Timestamp -- 也可以用MAX(Timestamp)取组内最新时间 FROM 你的数据表名 GROUP BY LEAST(No1, No2), GREATEST(No1, No2);
插入后你的表会新增两行汇总数据,格式大概是:
| No1 | No2 | Amount | Timestamp | |-----------|------|--------|---------------------| | 汇总_A-B | 汇总 | 40 | 202X-XX-XX XX:XX:XX | | 汇总_C-D | 汇总 | 60 | 202X-XX-XX XX:XX:XX |
写法2:保留分组固定顺序作为汇总行的No1/No2
如果希望汇总行的No1和No2保持统一的固定顺序(比如A-B而不是B-A),可以这么写:
INSERT INTO 你的数据表名 (No1, No2, Amount, Timestamp) SELECT LEAST(No1, No2) AS No1, GREATEST(No1, No2) AS No2, SUM(Amount) AS Amount, MAX(Timestamp) AS Timestamp -- 取该组最新的时间戳 FROM 你的数据表名 GROUP BY LEAST(No1, No2), GREATEST(No1, No2);
插入后新增的汇总行格式为:
| No1 | No2 | Amount | Timestamp | |-----|-----|--------|-------------| | A | B | 40 | 03.01.2018 | | C | D | 60 | 04.01.2018 |
额外需求:查询时同时展示原数据+汇总行
如果不想修改原表,只是查询时同时展示原数据和汇总行,可以用UNION ALL组合结果:
-- 原数据行 SELECT No1, No2, Amount, Timestamp FROM 你的数据表名 UNION ALL -- 汇总行 SELECT LEAST(No1, No2), GREATEST(No1, No2), SUM(Amount), MAX(Timestamp) FROM 你的数据表名 GROUP BY LEAST(No1, No2), GREATEST(No1, No2) ORDER BY LEAST(No1, No2), GREATEST(No1, No2), Timestamp;
注意事项
- 不同数据库的函数细节可能有差异:比如
CURRENT_TIMESTAMP在MySQL、SQL Server、PostgreSQL都能用,Oracle要换成SYSTIMESTAMP; - 要是怕重复插入汇总行,可以在
INSERT前加判断,比如WHERE NOT EXISTS (SELECT 1 FROM 你的数据表名 WHERE No1 = CONCAT('汇总_', LEAST(No1, No2), '-', GREATEST(No1, No2))); - 如果
No1和No2是数值类型,CONCAT要换成对应数据库的字符串拼接方式,比如MySQL的CONCAT_WS或者SQL Server的+。
内容的提问来源于stack exchange,提问作者ZerOne
相关产品推荐
相关产品推荐

