用 group by 配合聚合函数(如 sum、max)是合并重复记录数值最通用、最可控的方式;临时表仅在需多步处理时引入,非必需。核心是「按关键字段分组 → 对数值字段聚合」,须明确重复定义列与待合并数值列,避免漏写 group by 非聚合列导致报错;union all + group by 适合多源临时表合并,优于 join;不同聚合函数语义不同,不可混用;临时表应限于数据清洗或多次复用场景,命名需具业务含义;合并前须验证重复行的业务合理性。

直接说结论:用 GROUP BY 配合聚合函数(如 SUM、MAX)是合并重复记录数值最通用、最可控的方式;临时表只在需要多步中间处理时才引入,不是必须环节。
GROUP BY 合并重复数据的核心写法
本质是「按关键字段分组 → 对数值字段做聚合」。关键在于明确哪几列定义“重复”,哪些列要被合并(通常是数值型)。
- 如果只按
product_id合并销量:SELECT product_id, SUM(sales) AS total_sales FROM orders GROUP BY product_id - 如果需同时保留分类和品牌,并合并数量:
SELECT category, brand, SUM(quantity) AS qty_total FROM inventory GROUP BY category, brand - 错误示范:漏写
GROUP BY中的非聚合列,会触发ONLY_FULL_GROUP_BY报错,例如SELECT name, age, SUM(score) FROM students GROUP BY name——age既没在GROUP BY里,也没被聚合,MySQL 8.0+ 默认拒绝执行
UNION ALL + GROUP BY 处理多源临时表合并
当你要把多个结构一致的临时表(比如 #tmp1、#tmp2)里的同 ID 数值加总,UNION ALL 比 JOIN 更轻量、更可靠。
- 推荐写法:
SELECT id, SUM(num) AS total_num FROM (SELECT id, num FROM #tmp1 UNION ALL SELECT id, num FROM #tmp2) t GROUP BY id - 不用
UNION:它会去重再合并,可能意外丢掉本该相加的重复行 - 不建议用
FULL OUTER JOIN:SQL Server 支持,但 MySQL 不支持;即使支持,逻辑也更绕,且对 NULL 处理容易出错(比如ISNULL(t1.num,0)+ISNULL(t2.num,0)在三表以上就难维护) - 扩展性:加第三个表只需追加
UNION ALL SELECT id, num FROM #tmp3,无需改主逻辑
避免 GROUP BY 引发的语义歧义
合并数值不等于“随便挑一条”。不同聚合函数带来完全不同的业务含义:
-
SUM():适用于累加类指标(订单数、库存量、金额) -
MAX()或MIN():适用于取最新/最早状态(如最新审核时间、最高评分),但需确认字段语义是否允许丢弃其余值 -
STRING_AGG()(PostgreSQL/SQL Server 2017+)或GROUP_CONCAT()(MySQL):用于拼接字符串(如把同一用户的多个标签用分号连起来),不能用于数值合并 - 别用
AVG()替代SUM():平均值会掩盖总量变化,比如两个订单各 5 件,AVG是 5,SUM是 10 —— 后者才是真实吞吐量
临时表只是手段,不是目的
临时表适合两种情况:一是原始数据需清洗后再合并(比如先 WHERE status = 'valid' 过滤);二是后续还要多次引用合并结果。否则纯属增加 I/O 和维护成本。
- 能一步到位,就别拆成两步:
INSERT INTO #merged SELECT id, SUM(num) FROM #tmp1 GROUP BY id再查#merged,不如直接SELECT id, SUM(num) FROM #tmp1 GROUP BY id - 临时表命名要带上下文,比如
#sales_daily_merged比#tmp更易排查 - SQL Server 中临时表作用域限于当前会话,断开连接即销毁;MySQL 的
CREATE TEMPORARY TABLE同理 —— 别指望跨查询复用而不显式重建
真正容易被忽略的是:合并前是否已确认重复行的业务合理性?比如同一订单出现两次,是系统 bug 还是正常重试?盲目 GROUP BY 可能把问题掩盖掉。先查 HAVING COUNT(*) > 1 定位异常模式,再决定合并策略。










